home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / pdraw.zip / PDRAW.C < prev    next >
C/C++ Source or Header  |  1992-07-23  |  89KB  |  3,064 lines

  1. #ifdef SCCS
  2. static char sccsid[]="%W% Oki Electric Industry Co., Ltd. %E%";
  3. #endif
  4. /*
  5.  *            Copyright (c) 1991 by Stardent Computer Inc.
  6.  *            Copyright (c) 1992 by
  7.  *            Oki Electric Industry Co., Ltd.
  8.  *            All Rights Reserved
  9.  *
  10.  * Permission to use, copy, modify, and distribute this software and its
  11.  * documentation for any purpose and without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and that
  13.  * both that copyright notice and this permission notice appear in
  14.  * supporting documentation, and that the name of Oki not be
  15.  * used in advertising or publicity pertaining to distribution of the
  16.  * software without specific, written prior permission. Oki
  17.  * makes no representations about the suitability of this software for any
  18.  * purpose.  It is provided "as is" without express or implied warranty.
  19.  *
  20.  *************************************************************************
  21.  *
  22.  *                         P D R A W
  23.  *
  24.  *  A PEX/PHIGS drawing program, Version 1.2 entirely Motif based.
  25.  *
  26.  *  I expect that version 2.0 will still use Motif, but it will use Wcl
  27.  *  to create the widgets, instead of UIL.  It will also use Tcl.
  28.  *
  29.  *  This program was prepared for the tutorial PEX Programming: A mixture of
  30.  *  PHIGS, X and Motif, given at the Sixth Annual X Technical Conference,
  31.  *  January 1992, by Jan Hardenbergh.
  32.  *  Version 1.2 has the surface form, added for SIGGRAPH 92.
  33.  *
  34.  *  The files you will need for Version 1.0 are:
  35.  *   pdraw.c    - this file.  This contains all source (so much for modularity)
  36.  *   pdraw.uil  - The UI description for this program.
  37.  *   pdraw.man  - the manual page for pdraw - not much, but something.
  38.  *   Imakefile  - with micro make included.
  39.  *   
  40.  *
  41.  *************************************************************************/
  42. #define NO_TRANS 1 /* this enables transparency for Oki machines */
  43.  
  44. #include <stdlib.h>         /* for strtod() */
  45. #include <stdio.h>
  46. #include <Xm/Xm.h>          /* Motif Toolkit */
  47. #include <Mrm/MrmPublic.h>   /* Mrm */
  48. #include <Xm/ToggleB.h>     /* for XmToggleButtonGetState() */
  49. #include <X11/Xatom.h>
  50.  
  51. #include <math.h>
  52.  
  53. #include <phigs/phigs.h>
  54.  
  55. /*************************************************************************
  56.  * typedefs.
  57.  */
  58. typedef struct {
  59.   Ppoint3 point;
  60.   Pvec3   offset;
  61.   Pvec3   scale;
  62.   Pfloat  x_ang;
  63.   Pfloat  y_ang;
  64.   Pfloat  z_ang;
  65.   Pfloat  delta_x;
  66.   Pfloat  delta_y;
  67.   Pfloat  delta_z;
  68.   Pint    strux_id;
  69.   Pint    wk_id;
  70.   Display *dpy;
  71.   int     stop;
  72. } SpinInfo;
  73.  
  74. /*
  75.  * other business
  76.  */
  77. #if defined(SVR4_0) || defined(SVR4) || defined(hpux)
  78. #include <string.h>
  79. #define bcopy(b1,b2,len) memmove(b2, b1, len)
  80. #define bzero(b,len) memset(b, 0, len)
  81. #define bcmp(b1,b2,len) memcmp(b1, b2, len)
  82. #endif
  83.  
  84. #ifndef MAXFLOAT
  85. #define MAXFLOAT 10000000.0
  86. #endif
  87.  
  88. /*************************************************************************
  89.  *
  90.  *    F U N C T I O N    P R O T O T Y P E S
  91.  *
  92.  */
  93. static int applyViewSet(int viewNumber);
  94. static int getNumberWidgetValue(int id, float *value);
  95. static int setNumberWidgetValue(int id, float value);
  96. void InsertLine( long strux, Ppoint_list3 *points, int select );
  97. int Map2Points( int wkid, int firstX, int firstY, int secondX, int secondY,
  98.        Ppoint_list3 *points );
  99. void ResizeWorkstation(long wkid, int width, int height);
  100. void PickSomething( long wkid, int x, int y, long *struxID, long *elem);
  101. void SelectSomething( long strux, long element );
  102. void ClearSelection();
  103. void DumpStrux(long strux, long element, int pretty );
  104. void PrintElement( long struxID, long element, Pelem_type eType, long eSize,
  105.          Pelem_data *data );
  106. void InitStrux( long strux );
  107. void TranslateSelected( Ppoint_list3 *points );
  108. void DeleteSelected();
  109. void InsertTriStrip( long strux, Ppoint_list3 *points, int select );
  110. int MapPoints( int wkid, Ppoint_list3 *points );
  111. static void RotateObject(long wkid, long struxid, long count);
  112. static void StartSpinning(long wkid, long struxid, long count);
  113. Boolean oneSpin(char *client_data);
  114. static void StopSpinning(long wkid);
  115. static GC CreateDynGC(Widget drawArea);
  116. static int GetXPointsFromSelected(int *count, XPoint **points);
  117. static int MapWcPointsToX( int wkid, int view, Ppoint_list3 *wcPoints, 
  118.               XPoint *xPoints );
  119. static void DeleteAllStrux();
  120. static void MyPHIGSErrorHandler( Pint errnum, Pint funcnum, char *fname);
  121. static void build_sphere(long struxID);
  122. static void ApplySurfaceAttrs();
  123. /*
  124.  * event handler
  125.  */
  126. static void motionHandler( Widget widget,  XtPointer unused,
  127.               XMotionEvent *event,  Boolean *continue_to_dispatch);
  128.  
  129.  
  130. static void set_tool_pointer();
  131. static void set_tool_line();
  132. static void set_tool_view();
  133. static void set_tool_tristrip();
  134.  
  135. #define RADIAN(x) ((x)*(3.1415927 / 180.0))
  136.  
  137. /*************************************************************************
  138.  *
  139.  *    G L O B A L    V A R I A B L E S
  140.  *
  141.  */
  142.  
  143. static float theDepth = 0.5;
  144. static Pmatrix3 theMatOri, theMatMap;
  145.  
  146. static SpinInfo theSpinInfo;
  147. static Pint thePHIGSWorkstation = 1;
  148.  
  149. static MrmHierarchy theMrmHierarchy;     /* MRM database hierarchy ID */
  150.  
  151. int theAnchorX, theAnchorY, theDynX, theDynY, theAltX, theAltY;
  152. int theTriStripCount = 0;
  153. GC theDynGC = NULL;
  154.  
  155. #define TRIMAX 12
  156. Ppoint3 theTriPoints[TRIMAX];
  157.  
  158. float theTheta, thePhi, theDeltaTheta, theDeltaPhi;
  159. int thedebug;
  160.  
  161. #define LIGHTMAX 8
  162. int act[LIGHTMAX], deact[LIGHTMAX];
  163. Pint_list theLightsON = {0,act};    /* activation list */
  164. Pint_list theLightsOFF = {0,deact};    /* deactivation list */
  165.  
  166.  
  167. #define TOOL_POINTER 1
  168. #define TOOL_LINE 2
  169. #define TOOL_VIEW 3
  170. #define TOOL_TRISTRIP 4
  171.  
  172. static int theCurrentTool = TOOL_LINE;
  173.  
  174. #define SELECT_COLOR_IND 3
  175. static int theCurrentLineIndex = 1;
  176. #define INT_STYLE_ELEM 3
  177. #define REFL_EQN_ELEM 4
  178. #define REFL_PROPS_ELEM 5
  179. #define INT_SHAD_ELEM 6
  180. #define LIGHT_SRC_ELEM 7
  181. #define MATRIX_ELEM 8
  182. #define FACE_CULL_MODE 9
  183.  
  184. int theCullMode = (int)PCULL_NONE;
  185. int theShadeMode = (int)PSD_NONE;
  186. int theSolidMode = (int)PSTYLE_HOLLOW;
  187. static long theNewStrux = 0;
  188. Pstore thePHIGSStore = (Pstore)0;
  189. static int theUQUMFlag = 0;
  190. static Pint thePHIGSError = 0;
  191. static long theSelectedStrux, theSelectedElement = -1;
  192.  
  193. /*
  194.  * stretch selected stuff 
  195.  */
  196. static long theSelectedIndex; /* which point in list */
  197.  
  198.  
  199. XtAppContext    theAppContext;
  200.  
  201. static Widget theDrawingArea = NULL, /* the PEX area */
  202.               theViewForm = NULL,    /* the View Paramter Form */
  203.               theLightForm = NULL,   /* the Light Form */
  204.               theSurfaceForm = NULL,   /* the Surface Form */
  205.               theTopLevel = NULL,    /* global parent */
  206.             theFileForm = NULL;    /* archive file handler */
  207.  
  208. #define MAX_WIDGET 120
  209. static Widget widgetArray[MAX_WIDGET];
  210.  
  211. /*************************************************************************
  212.  *
  213.  * D Y N A M I C    F E E D B A C K   R O U T I N E S
  214.  *
  215.  */
  216. static void fbInitLine( XButtonPressedEvent *event );
  217. static void fbDynLine( XMotionEvent *event );
  218. static void fbEndLine( XButtonReleasedEvent *event );
  219.  
  220. static void fbDummy();
  221. static void fbEndPick( XButtonReleasedEvent *event );
  222.  
  223. static void fbInitTriStrip( XButtonPressedEvent *event );
  224. static void fbDynTriStrip( XMotionEvent *event );
  225. static void fbEndTriStrip( XButtonReleasedEvent *event );
  226. static void fbFinishTriStrip ( XButtonReleasedEvent *event );
  227.  
  228. static void fbInitView( XButtonPressedEvent *event );
  229. static void fbDynView( XMotionEvent *event );
  230. static void fbEndView( XButtonReleasedEvent *event );
  231.  
  232. static void fbInitTranslate( XButtonPressedEvent *event );
  233. /* use dynline */
  234. static void fbEndTranslate( XButtonReleasedEvent *event );
  235.  
  236. static void fbInitStretch( XButtonPressedEvent *event );
  237. /* use dynline, or dyntristrip */
  238. static void fbEndStretch( XButtonReleasedEvent *event );
  239.  
  240.  
  241. /*
  242.  * input dispatch tables
  243.  */
  244. typedef void (*pdrawHandler)();
  245. static pdrawHandler thePressHandlerTable[3] = 
  246.                 { fbInitLine, fbInitLine, fbInitLine };
  247. static pdrawHandler theMotionHandlerTable[3] = 
  248.                 { fbDynLine, fbDynLine, fbDynLine };
  249. static pdrawHandler theReleaseHandlerTable[3] = 
  250.                 { fbEndLine, fbEndLine, fbEndLine };
  251.  
  252. typedef int (*pdrawCmd)();
  253. static int ReadArchiveFile(char *filename);
  254. static int WriteArchiveFile(char *filename);
  255.  
  256. static pdrawCmd theFileCmd = { ReadArchiveFile };
  257.  
  258.        /* forward declaration of interface procedures */
  259. static void proc_pdraw_create();
  260. static void proc_pdraw_expose();
  261. static void proc_pdraw_resize();
  262. static void proc_pdraw_input();
  263. static void proc_pdraw_exit();
  264. static void proc_pdraw_activate();
  265. static void proc_pdraw_file();
  266.  
  267.        /* binding of uil procedure names with C functions */
  268. static MRMRegisterArg    regvec[] = {
  269.     {"proc_pdraw_exit",(caddr_t)proc_pdraw_exit},
  270.     {"proc_pdraw_create",(caddr_t)proc_pdraw_create},
  271.     {"proc_pdraw_expose",(caddr_t)proc_pdraw_expose},
  272.     {"proc_pdraw_resize",(caddr_t)proc_pdraw_resize},
  273.     {"proc_pdraw_input",(caddr_t)proc_pdraw_input},
  274.     {"proc_pdraw_activate",(caddr_t)proc_pdraw_activate},
  275.     {"proc_pdraw_file",(caddr_t)proc_pdraw_file}
  276.     };
  277. static MrmCount regnum = sizeof(regvec) / sizeof(MRMRegisterArg);
  278.  
  279. /*************************************************************************
  280.  *
  281.  *   C O N S T A N T S   U S E D   B Y   U I L
  282.  *
  283.  *
  284.  * why the &^%&^% these are not generated by UIL!.
  285.  * 
  286.  */
  287. #define    k_drawing_area 0
  288. #define    k_view_set 1
  289. #define    k_apply_vs 2
  290. #define    k_reset_vs 3
  291. #define    k_dismiss_vs 4
  292. #define    k_view_ref_pt_x 5
  293. #define    k_view_ref_pt_y 6
  294. #define    k_view_ref_pt_z 7
  295. #define    k_view_pl_norm_x 8
  296. #define    k_view_pl_norm_y 9
  297. #define    k_view_pl_norm_z 10
  298. #define    k_view_up_vect_x 11
  299. #define    k_view_up_vect_y 12
  300. #define    k_view_up_vect_z 13
  301. #define    k_proj_ref_pt_x 14
  302. #define    k_proj_ref_pt_y 15
  303. #define    k_proj_ref_pt_z 16
  304. #define    k_view_window_minx 17
  305. #define    k_view_window_maxx 18
  306. #define    k_view_window_miny 19
  307. #define    k_view_window_maxy 20
  308. #define    k_view_plane_dist 21
  309. #define    k_view_plane_back 22
  310. #define    k_view_plane_front 23
  311. #define    k_proj_vp_minx 24
  312. #define    k_proj_vp_maxx 25
  313. #define    k_proj_vp_miny 26
  314. #define    k_proj_vp_maxy 27
  315. #define    k_proj_vp_minz 28
  316. #define    k_proj_vp_maxz 29
  317. #define    k_proj_type_para 30
  318. #define    k_proj_type_persp 31
  319. #define    k_dump_strux 32
  320. #define    k_refresh 33
  321. #define    k_tool_pointer 34
  322. #define    k_tool_line 35
  323. #define    k_tool_view 36
  324. #define    k_tool_tristrip 37
  325. #define    k_delete 38
  326. #define    k_light 39
  327. #define    k_light_on1 40
  328. #define    k_light_on2 41
  329. #define    k_light_on3 42
  330. #define    k_light_on4 43
  331. #define    k_light_on5 44
  332. #define    k_light_on6 45
  333. #define    k_light_on7 46
  334. #define    k_light_on8 47
  335. #define    k_light_edit1 48
  336. #define    k_light_edit2 49
  337. #define    k_light_edit3 50
  338. #define    k_light_edit4 51
  339. #define    k_light_edit5 52
  340. #define    k_light_edit6 53
  341. #define    k_light_edit7 54
  342. #define    k_light_edit8 55
  343. #define    k_light_type_ambient 56
  344. #define    k_light_type_directional 57
  345. #define    k_light_type_positional 58
  346. #define    k_light_type_spot 59
  347. #define    k_light_pos_x 60
  348. #define    k_light_pos_y 61
  349. #define    k_light_pos_z 62
  350. #define    k_light_color_red 63
  351. #define    k_light_color_green 64
  352. #define    k_light_color_blue 65
  353. #define    k_light_direction_x 66
  354. #define    k_light_direction_y 67
  355. #define    k_light_direction_z 68
  356. #define    k_light_coeff_const 69
  357. #define    k_light_coeff_dist 70
  358. #define    k_light_conc_exp 71
  359. #define    k_light_spread_angle 72
  360. #define    k_apply_light 73
  361. #define    k_reset_light 74
  362. #define    k_dismiss_light 75
  363. #define    k_surface 76
  364. #define    k_FREE 77
  365. #define    k_spin_strux  78
  366. #define    k_spin_slowly  79
  367. #define    k_save 80
  368. #define    k_read 81
  369. #define    k_file 82
  370. #define    k_undo 83
  371. #define    k_file_help 84
  372. #define    k_delete_all 85
  373. #define    k_face_cull 86
  374. #define    k_sphere 87
  375. #define    k_dismiss_surface 88
  376. #define    k_reset_surface 89
  377. #define    k_apply_surface 90
  378. #define    k_surface_refl_transparency 91
  379. #define    k_surface_refl_specexp 92
  380. #define    k_surface_refl_specular 93
  381. #define    k_surface_refl_diffuse 94
  382. #define    k_surface_refl_ambient 95
  383. #define    k_sstyle_empty 96
  384. #define    k_sstyle_solid 97
  385. #define    k_sstyle_hollow 98
  386. #define    k_sshade_flat 99
  387. #define    k_sshade_gouraud 100
  388. #define    k_sshade_dot 101
  389. #define    k_sshade_phong 102
  390. #define    k_cull_none 103
  391. #define    k_cull_back 104
  392. #define    k_cull_front 105
  393.  
  394.  
  395. /*
  396.  * number strings
  397.  */
  398. static char *numberStrings[] = {
  399.   "",                /* k_drawing_area 0 */
  400.   "",                /* k_view_set 1 */
  401.   "",                /* k_apply_vs 2 */
  402.   "",                /* k_reset_vs 3 */
  403.   "",                /* k_dismiss_vs 4 */
  404.   "view_ref_pt_x",        /* k_view_ref_pt_x 5 */
  405.   "view_ref_pt_y",        /* k_view_ref_pt_y 6 */
  406.   "view_ref_pt_z",        /* k_view_ref_pt_z 7 */
  407.   "view_pl_norm_x",        /* k_view_pl_norm_x 8 */
  408.   "view_pl_norm_y",        /* k_view_pl_norm_y 9 */
  409.   "view_pl_norm_z",        /* k_view_pl_norm_z 10 */
  410.   "view_up_vect_x",        /* k_view_up_vect_x 11 */
  411.   "view_up_vect_y",        /* k_view_up_vect_y 12 */
  412.   "view_up_vect_z",        /* k_view_up_vect_z 13 */
  413.   "view_window_minx",        /* k_view_window_minx 17 */
  414.   "view_window_maxx",        /* k_view_window_maxx 18 */
  415.   "view_window_miny",        /* k_view_window_miny 19 */
  416.   "view_window_maxy",        /* k_view_window_maxy 20 */
  417.   "view_plane_dist",        /* k_view_plane_dist 21 */
  418.   "view_plane_back",        /* k_view_plane_back 22 */
  419.   "view_plane_front",        /* k_view_plane_front 23 */
  420.   "proj_vp_minx",        /* k_proj_vp_minx 24 */
  421.   "proj_vp_maxx",        /* k_proj_vp_maxx 25 */
  422.   "proj_vp_miny",        /* k_proj_vp_miny 26 */
  423.   "proj_vp_maxy",        /* k_proj_vp_maxy 27 */
  424.   "proj_vp_minz",        /* k_proj_vp_minz 28 */
  425.   "proj_vp_maxz",        /* k_proj_vp_maxz 29 */
  426.   "proj_type_para",        /* k_proj_type_para 30 */
  427.   "proj_type_persp",        /* k_proj_type_persp 31 */
  428.     "dump_strux",        /* k_dump_strux 32 */
  429.     "refresh",        /* k_refresh 33 */
  430.     "tool_pointer",        /* k_tool_pointer 34 */
  431.     "tool_line",        /* k_tool_line 35 */
  432.     "tool_view",        /* k_tool_view 36 */
  433.     "tool_tristrip",        /* k_tool_tristrip 37 */
  434.     "delete",        /* k_delete 38 */
  435.     "light",        /* k_light 39 */
  436.     "light_on1",        /* k_light_on1 40 */
  437.     "light_on2",        /* k_light_on2 41 */
  438.     "light_on3",        /* k_light_on3 42 */
  439.     "light_on4",        /* k_light_on4 43 */
  440.     "light_on5",        /* k_light_on5 44 */
  441.     "light_on6",        /* k_light_on6 45 */
  442.     "light_on7",        /* k_light_on7 46 */
  443.     "light_on8",        /* k_light_on8 47 */
  444.     "light_edit1",        /* k_light_edit1 48 */
  445.     "light_edit2",        /* k_light_edit2 49 */
  446.     "light_edit3",        /* k_light_edit3 50 */
  447.     "light_edit4",        /* k_light_edit4 51 */
  448.     "light_edit5",        /* k_light_edit5 52 */
  449.     "light_edit6",        /* k_light_edit6 53 */
  450.     "light_edit7",        /* k_light_edit7 54 */
  451.     "light_edit8",        /* k_light_edit8 55 */
  452.     "light_type_ambient",        /* k_light_type_ambient 56 */
  453.     "light_type_directional",        /* k_light_type_directional 57 */
  454.     "light_type_positional",        /* k_light_type_positional 58 */
  455.     "light_type_spot",        /* k_light_type_spot 59 */
  456.     "light_pos_x",        /* k_light_pos_x 60 */
  457.     "light_pos_y",        /* k_light_pos_y 61 */
  458.     "light_pos_z",        /* k_light_pos_z 62 */
  459.     "light_color_red",        /* k_light_color_red 63 */
  460.     "light_color_green",        /* k_light_color_green 64 */
  461.     "light_color_blue",        /* k_light_color_blue 65 */
  462.     "light_direction_x",        /* k_light_direction_x 66 */
  463.     "light_direction_y",        /* k_light_direction_y 67 */
  464.     "light_direction_z",        /* k_light_direction_z 68 */
  465.     "light_coeff_const",        /* k_light_coeff_const 69 */
  466.     "light_coeff_dist",        /* k_light_coeff_dist 70 */
  467.     "light_conc_exp",        /* k_light_conc_exp 71 */
  468.     "light_spread_angle",        /* k_light_spread_angle 72 */
  469.     "apply_light",        /* k_apply_light 73 */
  470.     "reset_light",        /* k_reset_light 74 */
  471.     "dismiss_light",        /* k_dismiss_light 75 */
  472.     "surface",        /* k_surface 76 */
  473.     "FREE",        /* k_FREE 77 */
  474.     "spin_strux",        /* k_spin_strux  78 */
  475.     "spin_slowly",        /* k_spin_slowly  79 */
  476.     "save",        /* k_save 80 */
  477.     "read",        /* k_read 81 */
  478.     "file",        /* k_file 82 */
  479.     "undo",        /* k_undo 83 */
  480.     "file_help",        /* k_file_help 84 */
  481.     "delete_all",        /* k_delete_all 85 */
  482.     "face_cull",        /* k_face_cull 86 */
  483.     "sphere",        /* k_sphere 87 */
  484.     "dismiss_surface",        /* k_dismiss_surface 88 */
  485.     "reset_surface",        /* k_reset_surface 89 */
  486.     "apply_surface",        /* k_apply_surface 90 */
  487.     "surface_refl_transparency",        /* k_surface_refl_transparency 91 */
  488.     "surface_refl_specexp",        /* k_surface_refl_specexp 92 */
  489.     "surface_refl_specular",        /* k_surface_refl_specular 93 */
  490.     "surface_refl_diffuse",        /* k_surface_refl_diffuse 94 */
  491.     "surface_refl_ambient",        /* k_surface_refl_ambient 95 */
  492.     "sstyle_empty",        /* k_sstyle_empty 96 */
  493.     "sstyle_solid",        /* k_sstyle_solid 97 */
  494.     "sstyle_hollow",        /* k_sstyle_hollow 98 */
  495.     "sshade_flat",        /* k_sshade_flat 99 */
  496.     "sshade_gouraud",        /* k_sshade_gouraud 100 */
  497.     "sshade_dot",        /* k_sshade_dot 101 */
  498.     "sshade_phong",        /* k_sshade_phong 102 */
  499.     "cull_none",        /* k_cull_none 103 */
  500.     "cull_back",        /* k_cull_back 104 */
  501.     "cull_front"        /* k_cull_front 105 */
  502. };
  503. static int numberStringCount = sizeof(numberStrings) / sizeof(char *);
  504.  
  505. /******************************************************************
  506.  *
  507.  *     M A I N
  508.  */
  509. int main(argc, argv)
  510. int argc;
  511. char **argv;
  512. {
  513.   Widget pdrawmain;
  514.   Arg arglist[1];
  515.   int n;
  516.   MrmCode class;
  517.   char *files[1];
  518.  
  519.   MrmInitialize ();
  520.  
  521.   theTopLevel = XtAppInitialize(&theAppContext, "pdraw", 
  522.                    (XrmOptionDescList)NULL , 0,
  523.                    (Cardinal*)&argc, (String*)argv, 
  524.                    (String*)NULL, (ArgList)NULL, 0);
  525.  
  526.   /*
  527.    *  Open the User Interface Description file. 
  528.    *    pdraw.uil is compiled into pdraw.uid
  529.    */ 
  530.   files[0] = "pdraw.uid";
  531.   if (MrmOpenHierarchy( 1, files, NULL, &theMrmHierarchy) != MrmSUCCESS) {
  532.     printf ("can't open pdraw.uid\n");
  533.     exit(0);
  534.   }
  535.  
  536.   if (MrmRegisterNames (regvec, regnum) != MrmSUCCESS) {
  537.     printf("can't register names\n");
  538.     exit(0) ;
  539.   }
  540.  
  541.   if (MrmFetchWidget (theMrmHierarchy, "pdraw_obj_main",
  542.               theTopLevel, &pdrawmain, &class)
  543.       != MrmSUCCESS) {
  544.     printf("can't fetch interface\n");
  545.     exit(0);
  546.   }
  547.  
  548.   XtManageChild(pdrawmain);
  549.     
  550.   XtRealizeWidget(theTopLevel);
  551.  
  552.   /*
  553.    *  Init PHIGS and other boring stuff.
  554.    */
  555.   
  556.   InitPHIGS();
  557.  
  558.   XtAppMainLoop(theAppContext);  /* Hand over control to the UI & User */
  559.  
  560. }
  561.  
  562. /*************************************************************************
  563.  * InitPHIGS
  564.  *
  565.  * Open PHIGS using popen_xphigs
  566.  */
  567. InitPHIGS()
  568. {
  569.   Pxphigs_info info;
  570.   Pconnid_x_drawable connid;
  571.   long i = 0;
  572.   Pint struxid = 1;
  573.   Ppoint3 p[6], *pp;
  574.   Ppoint_list3 plist;
  575.   Pint wsType = 0;
  576.   void (*perr_hand)(); /* this will be perr_hand, so no need to save it */
  577.   XWindowAttributes        winAttrs;
  578.   VisualID visualID;
  579.   XStandardColormap  *scm;
  580.   Atom myAtom;
  581.   char atomName[80];
  582.   int count;
  583.  
  584.   info.display = XtDisplay(theDrawingArea);
  585.   info.flags.no_monitor = 1;
  586.   popen_xphigs( NULL, 0, PXPHIGS_INFO_DISPLAY | PXPHIGS_INFO_FLAGS_NO_MON,
  587.            &info );
  588.   /*
  589.    * try to create a workstation that uses a RGB_DEFAULT_MAP colormap.
  590.    * this will prevent color flashing ( technicolor )
  591.    */
  592.   XGetWindowAttributes(XtDisplay(theDrawingArea),XtWindow(theDrawingArea),
  593.                &winAttrs);
  594.   visualID =  XVisualIDFromVisual(winAttrs.visual);
  595.   if (XGetRGBColormaps(XtDisplay(theDrawingArea), 
  596.                RootWindow(XtDisplay(theDrawingArea),
  597.                   XScreenNumberOfScreen(winAttrs.screen)),
  598.                &scm, &count, XA_RGB_DEFAULT_MAP )) {
  599.     printf("have a RGB_DEFAULT_MAP = count = %d\n", count );
  600.     for (i = 0; i < count; i++, scm++ ) {
  601.       if ( scm->visualid == visualID ) {
  602.     printf("got a match\n");
  603.     sprintf (atomName, "RGB_PEX_MAP_%d", visualID); 
  604.     myAtom = XInternAtom( XtDisplay(theDrawingArea), atomName, False );
  605.     XChangeProperty(XtDisplay(theDrawingArea), 
  606.             RootWindow(XtDisplay(theDrawingArea),
  607.                    XScreenNumberOfScreen(winAttrs.screen)),
  608.             myAtom, XA_RGB_COLOR_MAP, 32, PropModeReplace,
  609.             (unsigned char *)scm, sizeof(XStandardColormap)/4 );
  610.     wsType = phigs_ws_type_create( phigs_ws_type_x_drawable,
  611.                       PHIGS_X_CMAP_PROP_ATOM, (char *)myAtom,
  612.                       PHIGS_X_BUF_MODE, PHIGS_BUF_DOUBLE,
  613.                       NULL );
  614.     break;
  615.       }
  616.     }
  617.   }
  618.   /*
  619.    * create a workstation that is output only, double buffers, at the least.
  620.    */
  621.   if (wsType == 0 ) 
  622.     wsType = phigs_ws_type_create( phigs_ws_type_x_drawable,
  623.                   PHIGS_X_BUF_MODE, PHIGS_BUF_DOUBLE,
  624.                   NULL );
  625.   /*
  626.    * open a PHIGS workstation in the drawing area.
  627.    */
  628.   connid.display = XtDisplay(theDrawingArea);
  629.   connid.drawable_id = XtWindow(theDrawingArea);
  630.   popen_ws(thePHIGSWorkstation, (Pconnid)&connid, wsType );
  631.  
  632.   pset_hlhsr_mode(thePHIGSWorkstation, PHIGS_HLHSR_MODE_ZBUFF);
  633.   pset_disp_upd_st(thePHIGSWorkstation, PDEFER_WAIT, PMODE_NIVE );
  634.  
  635. /*
  636.  * we want to work in view 1, so when points get mapped make sure they 
  637.  * have a preference for view 1.
  638.  */
  639.   pset_view_tran_in_pri(thePHIGSWorkstation, 1, 0, PPRI_HIGHER );
  640.  
  641. /*
  642.  * Just turn some lights on for the heck of it.
  643.  */
  644.   InitLights(thePHIGSWorkstation);
  645.  
  646.   popen_struct(struxid);
  647.  
  648.   pset_view_ind(1);
  649.  
  650.   pset_linewidth(3.0);
  651.  
  652.   plist.points = p;
  653.   pp = (Ppoint3 *)p;
  654.   pp->x = 0.5; pp->y = 0.0; pp->z = 0.0; pp++;
  655.   pp->x = 1.0; pp->y = 1.0; pp->z = 0.0; pp++;
  656.   pp->x = 0.5; pp->y = 0.0; pp->z = 1.0; pp++;
  657.   pp->x = 0.5; pp->y = 0.0; pp->z = -1.0; pp++;
  658.   pp->x = 0.5; pp->y = 1.0; pp->z = -1.0; pp++;
  659.   pp->x = 1.0; pp->y = 0.0; pp->z = 0.0;
  660.   plist.num_points = 6;
  661.   ppolyline3( &plist );
  662.   pclose_struct();
  663.   
  664.   ppost_struct (thePHIGSWorkstation, struxid, 0.0);
  665.  
  666.   applyViewSet(1);
  667.  
  668.   predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  669.  
  670.   theDynGC = CreateDynGC(theDrawingArea);
  671.  
  672.   theSpinInfo.stop = 1;
  673.  
  674.   thePHIGSError = 0;                 /* see MyPHIGSErrorHandler */
  675.   pset_err_hand( &MyPHIGSErrorHandler, &perr_hand);
  676. }
  677.  
  678. /*************************************************************************
  679.  *
  680.  *    U S E R    I N T E R F A C E    C A L L B A C K S
  681.  *
  682.  *  All UI callbacks are also defined in pdraw.uil and begin proc_pdraw_??
  683.  *
  684.  */
  685.  
  686. static void proc_pdraw_create( widget, tag, cbData )
  687.     Widget    widget;
  688.     int    *tag;
  689.     XmAnyCallbackStruct *cbData;
  690. {
  691.     Arg arg ;
  692.     int which = *(int *)tag;
  693.  
  694.     switch (which) {
  695.     case k_drawing_area:
  696.     theDrawingArea = widget;
  697.     XtAddEventHandler( theDrawingArea, ButtonMotionMask, FALSE, motionHandler, NULL );
  698.  
  699.     break;
  700.  
  701.       case k_view_set:
  702.     theViewForm = widget;
  703.     break;
  704.     
  705.       case k_light:
  706.     theLightForm = widget;
  707.     break;
  708.  
  709.       case k_file:
  710.     theFileForm = widget;
  711.     break;
  712.  
  713.       default: 
  714.     if (which > MAX_WIDGET) {
  715.       printf(" got widget #%d, MAX is still %d\n",which,MAX_WIDGET);
  716.       return;
  717.     }
  718.     widgetArray[which] = widget;
  719.     break;
  720.     }
  721. }
  722.  
  723. static void proc_pdraw_expose( widget, tag, cbData )
  724.     Widget    widget;
  725.     int    *tag;
  726.     XmAnyCallbackStruct *cbData;
  727. {
  728.   predraw_all_structs( thePHIGSWorkstation, PFLAG_ALWAYS );
  729. }
  730.  
  731.  
  732. static void proc_pdraw_resize( widget, tag, cbData )
  733.     Widget    widget;
  734.     int    *tag;
  735.     XmAnyCallbackStruct *cbData;
  736. {
  737.   XWindowAttributes winAttrs;
  738.  
  739.   /*
  740.    * I'm positive this is a terrible hack in violation of all of Xt
  741.    * rules and regulations, but event was not comming back in call_back data.
  742.    */
  743.   XGetWindowAttributes(XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
  744.                &winAttrs );
  745.  
  746.   ResizeWorkstation( thePHIGSWorkstation, winAttrs.width, winAttrs.height );
  747.   predraw_all_structs( thePHIGSWorkstation, PFLAG_ALWAYS );
  748. }
  749.  
  750.  
  751. static void proc_pdraw_input( widget, tag, cbData )
  752.     Widget    widget;
  753.     int    *tag;
  754.     XmAnyCallbackStruct *cbData;
  755. {
  756.   XEvent *event = cbData->event;
  757.  
  758.   if (event->xbutton.button < 1 || event->xbutton.button > 3) return;
  759.  
  760.   if (event->type ==  ButtonPress) {
  761.     thePressHandlerTable[event->xbutton.button-1](event);
  762.   } else if (event->type ==  ButtonRelease) {
  763.     theReleaseHandlerTable[event->xbutton.button-1](event);
  764.   }
  765.  
  766. }
  767.  
  768. static void proc_pdraw_exit( widget, tag, cbData )
  769.     Widget    widget;
  770.     char    *tag;
  771.     XmAnyCallbackStruct *cbData;
  772. {
  773.     exit(0);
  774. }
  775.  
  776. /*************************************************************************
  777.  *
  778.  *   P R O C _ P D R A W _ A C T I V A T E
  779.  */
  780. static void proc_pdraw_activate( widget, tag, cbData )
  781.     Widget    widget;
  782.     char    *tag;
  783.     XmAnyCallbackStruct *cbData;
  784. {
  785.   int which = *(int *)tag;
  786.   MrmCode class;
  787.  
  788.  
  789.   switch (which) {
  790.   case k_view_set:
  791.     if (theViewForm == NULL) {     /* The first time, fetch order box. */
  792.       if (MrmFetchWidget(theMrmHierarchy, "file_dialog", theTopLevel,
  793.              &theViewForm, &class) != MrmSUCCESS) {
  794.     printf("can't fetch order box widget");
  795.     return;
  796.       }
  797.     }
  798.  
  799.     if (XtIsManaged(theViewForm))
  800.       XtUnmanageChild(theViewForm);
  801.     else
  802.       XtManageChild(theViewForm);
  803.     break;
  804.  
  805.   case k_apply_vs:
  806.     applyViewSet(1);
  807.     break;
  808.  
  809.   case k_reset_vs:
  810.     break;
  811.  
  812.   case k_dismiss_vs:
  813.     XtUnmanageChild(theViewForm);
  814.     break;
  815.  
  816.   case k_dump_strux:
  817.     if ( theSelectedElement != -1 ) {
  818.       DumpStrux(theSelectedStrux, -1, 1 ); 
  819.     } else {
  820.       DumpStrux(theNewStrux, -1, 1 ); 
  821.     }
  822.     break;
  823.  
  824.   case k_refresh:
  825.     predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  826.     break;
  827.  
  828.   case k_tool_pointer:
  829.     set_tool_pointer();
  830.     break;
  831.  
  832.   case k_tool_line:
  833.     set_tool_line();
  834.     break;
  835.  
  836.   case k_tool_view:
  837.     set_tool_view();
  838.     break;
  839.  
  840.   case k_tool_tristrip:
  841.     set_tool_tristrip();
  842.     break;
  843.  
  844.   case k_delete:
  845.     DeleteSelected();
  846.     predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  847.     break;
  848.  
  849.   case k_light:
  850.     if (theLightForm == NULL) {     /* The first time, fetch order box. */
  851.       if (MrmFetchWidget(theMrmHierarchy, "light_dialog", theTopLevel,
  852.              &theLightForm, &class) != MrmSUCCESS) {
  853.     printf("can't fetch light form widget");
  854.     return;
  855.       }
  856.     }
  857.  
  858.     if (XtIsManaged(theLightForm))
  859.       XtUnmanageChild(theLightForm);
  860.     else
  861.       XtManageChild(theLightForm);
  862.     break;
  863.  
  864.   case k_apply_light:
  865.     break;
  866.  
  867.   case k_reset_light:
  868.     break;
  869.  
  870.   case k_dismiss_light:
  871.     XtUnmanageChild(theLightForm);
  872.     break;
  873.  
  874.   case k_surface:
  875.     if (theSurfaceForm == NULL) {     /* The first time, fetch order box. */
  876.       if (MrmFetchWidget(theMrmHierarchy, "surface_dialog", theTopLevel,
  877.              &theSurfaceForm, &class) != MrmSUCCESS) {
  878.     printf("can't fetch surface form widget");
  879.     return;
  880.       }
  881.     }
  882.  
  883.     if (XtIsManaged(theSurfaceForm))
  884.       XtUnmanageChild(theSurfaceForm);
  885.     else
  886.       XtManageChild(theSurfaceForm);
  887.     break;
  888.  
  889.   case k_apply_surface:
  890.     ApplySurfaceAttrs();
  891.     predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  892.     break;
  893.  
  894.   case k_reset_surface:
  895.     break;
  896.  
  897.   case k_dismiss_surface:
  898.     XtUnmanageChild(theSurfaceForm);
  899.     break;
  900.  
  901. #if 0
  902.   case 9999:
  903.     if ( ++theSolidMode > (int)PSTYLE_SOLID )
  904.       theSolidMode = (int)PSTYLE_HOLLOW;
  905.     if ( theSelectedElement != -1 ) {
  906.       ChangeStruxAttr( theSelectedStrux, INT_STYLE_ELEM, theSolidMode );
  907.     } else {
  908.       ChangeStruxAttr( theNewStrux, INT_STYLE_ELEM, theSolidMode );
  909.     }
  910.     predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  911.     break;
  912.  
  913.   case 9998:
  914.     /* really should inquire what methods are available!!! */
  915.     if ( ++theShadeMode > (int)PSD_COLOUR ) theShadeMode = (int)PSD_NONE;
  916.     if ( theSelectedElement != -1 ) {
  917.       ChangeStruxAttr( theSelectedStrux, INT_SHAD_ELEM, theShadeMode );
  918.     } else {
  919.       ChangeStruxAttr( theNewStrux, INT_SHAD_ELEM, theShadeMode );
  920.     }
  921.     predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  922.     break;
  923.  
  924.   case 9997:
  925.     if ( ++theCullMode > (int)PCULL_FRONTFACE ) theCullMode = (int)PCULL_NONE;
  926.     if ( theSelectedElement != -1 ) {
  927.       ChangeStruxAttr( theSelectedStrux, FACE_CULL_MODE, theCullMode );
  928.     } else {
  929.       ChangeStruxAttr( theNewStrux, FACE_CULL_MODE, theCullMode );
  930.     }
  931.     predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  932.     break;
  933. #endif
  934.  
  935.   case k_spin_strux:
  936.     if ( theSelectedElement != -1 ) {
  937.       RotateObject( thePHIGSWorkstation, theSelectedStrux, 20 );
  938.     } else {
  939.       RotateObject( thePHIGSWorkstation, theNewStrux, 20 );
  940.     }
  941.     break;
  942.  
  943.   case k_spin_slowly:
  944.     if (!theSpinInfo.stop) {
  945.       StopSpinning( thePHIGSWorkstation );
  946.     } else {
  947.       if ( theSelectedElement != -1 ) {
  948.       StartSpinning( thePHIGSWorkstation, theSelectedStrux, 120 );
  949.     } else {
  950.       StartSpinning( thePHIGSWorkstation, theNewStrux, 120 );
  951.     }
  952.  
  953.     }
  954.     break;
  955.  
  956.   case k_sphere:
  957.     build_sphere(112);
  958.     predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  959.     break;
  960.  
  961.   case k_read:
  962.   case k_save:
  963.     if (theFileForm == NULL) {     /* The first time, fetch order box. */
  964.       if (MrmFetchWidget(theMrmHierarchy, "file_dialog", theTopLevel,
  965.              &theFileForm, &class) != MrmSUCCESS) {
  966.     printf("can't fetch order box widget");
  967.     return;
  968.       }
  969.     }
  970.  
  971.     theFileCmd = (which == k_read)?ReadArchiveFile:WriteArchiveFile;
  972.  
  973.     if (XtIsManaged(theFileForm))
  974.       XtUnmanageChild(theFileForm);
  975.     else
  976.       XtManageChild(theFileForm);
  977.     break;
  978.  
  979.   case k_undo:
  980.     break;
  981.  
  982.   case k_file_help:
  983.     break;
  984.  
  985.   case k_delete_all:
  986.     DeleteAllStrux();
  987.     break;
  988.  
  989.   default:
  990.     break;
  991.   }
  992.     
  993. }
  994.  
  995. /*************************************************************************
  996.  * proc_pdraw_file
  997.  *
  998.  * handle callback fron file selection mechanism.
  999.  */
  1000. static void proc_pdraw_file( widget, tag, cbData )
  1001.     Widget    widget;
  1002.     char    *tag;
  1003.     XmFileSelectionBoxCallbackStruct *cbData;
  1004. {
  1005.   char *filename;
  1006.   int status;
  1007.  
  1008.   switch (cbData->reason) {
  1009.   case XmCR_OK:
  1010.   case XmCR_APPLY:
  1011.     if (!XmStringGetLtoR(cbData->value, XmSTRING_DEFAULT_CHARSET, 
  1012.              &filename )) {
  1013.       printf("imagine a popup...\n");
  1014.     } else {
  1015.       status = theFileCmd(filename);
  1016.       predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  1017.     }
  1018.     if (cbData->reason == XmCR_OK) XtUnmanageChild(theFileForm);
  1019.     break;
  1020.  
  1021.   case XmCR_CANCEL:
  1022.     XtUnmanageChild(theFileForm);
  1023.     break;
  1024.  
  1025.   case XmCR_HELP:
  1026.     break;
  1027.  
  1028.   default:
  1029.     break;
  1030.   }
  1031. }
  1032.  
  1033.  
  1034.  
  1035.  
  1036. /*************************************************************************
  1037.  *
  1038.  *  T O O L   S E L E C T I O N   R O U T I N E S
  1039.  *
  1040.  *************************************************************************
  1041.  */
  1042.  
  1043. static void set_tool_pointer()
  1044. {
  1045.   if (theCurrentTool != TOOL_POINTER) {
  1046.     theCurrentTool = TOOL_POINTER;
  1047.  
  1048.     /*
  1049.      * don't deal with fancy pre-pick hilite, yet.
  1050.      */
  1051.     thePressHandlerTable[0] = fbDummy;
  1052.     theMotionHandlerTable[0] = fbDummy;
  1053.     theReleaseHandlerTable[0] = fbEndPick;
  1054.  
  1055.     thePressHandlerTable[1] = fbInitTranslate;
  1056.     theMotionHandlerTable[1] = fbDynLine;
  1057.     theReleaseHandlerTable[1] = fbEndTranslate;
  1058.  
  1059.     thePressHandlerTable[2] = fbInitStretch;
  1060.     theMotionHandlerTable[2] = fbDummy;
  1061.     theReleaseHandlerTable[2] = fbEndStretch;
  1062.   }
  1063. }
  1064.  
  1065. static void set_tool_line()
  1066. {
  1067.   if (theCurrentTool != TOOL_LINE) {
  1068.     theCurrentTool = TOOL_LINE;
  1069.  
  1070.     thePressHandlerTable[0] = fbInitLine;
  1071.     theMotionHandlerTable[0] = fbDynLine;
  1072.     theReleaseHandlerTable[0] = fbEndLine;
  1073.  
  1074.     thePressHandlerTable[1] = fbInitLine;
  1075.     theMotionHandlerTable[1] = fbDynLine;
  1076.     theReleaseHandlerTable[1] = fbEndLine;
  1077.  
  1078.     thePressHandlerTable[2] = fbInitView;
  1079.     theMotionHandlerTable[2] = fbDynView;
  1080.     theReleaseHandlerTable[2] = fbEndView;
  1081.   }
  1082. }
  1083.  
  1084. static void set_tool_view()
  1085. {
  1086.   if (theCurrentTool != TOOL_VIEW) {
  1087.     theCurrentTool = TOOL_VIEW;
  1088.     thePressHandlerTable[0] = fbInitView;
  1089.     theMotionHandlerTable[0] = fbDynView;
  1090.     theReleaseHandlerTable[0] = fbEndView;
  1091.  
  1092.     thePressHandlerTable[1] = fbDummy;
  1093.     theMotionHandlerTable[1] = fbDummy;
  1094.     theReleaseHandlerTable[1] = fbDummy;
  1095.  
  1096.     thePressHandlerTable[2] = fbInitView;
  1097.     theMotionHandlerTable[2] = fbDynView;
  1098.     theReleaseHandlerTable[2] = fbEndView;
  1099.   }
  1100. }
  1101.  
  1102. static void set_tool_tristrip()
  1103. {
  1104.   if (theCurrentTool != TOOL_TRISTRIP) {
  1105.     theCurrentTool = TOOL_TRISTRIP;
  1106.  
  1107.     thePressHandlerTable[0] = fbInitTriStrip;
  1108.     theMotionHandlerTable[0] = fbDynTriStrip;
  1109.     theReleaseHandlerTable[0] = fbEndTriStrip;
  1110.  
  1111.     thePressHandlerTable[1] = fbFinishTriStrip;
  1112.     theMotionHandlerTable[1] = fbDummy;
  1113.     theReleaseHandlerTable[1] = fbDummy;
  1114.  
  1115.     thePressHandlerTable[2] = fbInitView;
  1116.     theMotionHandlerTable[2] = fbDynView;
  1117.     theReleaseHandlerTable[2] = fbEndView;
  1118.   }
  1119. }
  1120.  
  1121. /*************************************************************************
  1122.  *
  1123.  * D Y N A M I C     F E E D B A C K     R O U T I N E S
  1124.  *
  1125.  */
  1126. static void fbInitLine( XButtonPressedEvent *event )
  1127. {
  1128.   XGCValues values;
  1129.  
  1130.   if (!theDynGC) {
  1131.     values.function = GXinvert;
  1132.     theDynGC = XCreateGC( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), 
  1133.              GCFunction, &values );
  1134.   }
  1135.   theAnchorX = event->x;
  1136.   theAnchorY = event->y;
  1137.   theDynX = event->x;
  1138.   theDynY = event->y;
  1139.   XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1140.         theAnchorX, theAnchorY, theDynX, theDynY );
  1141. }
  1142.  
  1143. static void fbDynLine( XMotionEvent *event )
  1144. {
  1145.   XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1146.         theAnchorX, theAnchorY, theDynX, theDynY );
  1147.   theDynX = event->x;
  1148.   theDynY = event->y;
  1149.   XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1150.         theAnchorX, theAnchorY, theDynX, theDynY );
  1151. }
  1152.  
  1153. static void fbEndLine( XButtonReleasedEvent *event )
  1154. {
  1155.   Ppoint_list3 points;
  1156.   Ppoint3 pl[2];
  1157.  
  1158.   points.points = pl;
  1159.  
  1160.   if (Map2Points(thePHIGSWorkstation, theAnchorX, theAnchorY, theDynX, theDynY,
  1161.          &points)) {
  1162.     if (theNewStrux == 0) {
  1163.       theNewStrux = 111;
  1164.       InitStrux(theNewStrux);
  1165.     }
  1166.     InsertLine(theNewStrux, &points, 1 );
  1167.     if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  1168.   }
  1169. }
  1170.  
  1171.  
  1172. /*
  1173.  * no dynamic hiliting
  1174.  */
  1175. static void fbDummy() {}
  1176.  
  1177. static void fbEndPick( XButtonReleasedEvent *event )
  1178. {
  1179.   long s, e;
  1180.  
  1181.   XDrawPoint(  XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1182.          event->x, event->y );
  1183.   if ( theSelectedElement != -1 ) ClearSelection();
  1184.   PickSomething( thePHIGSWorkstation, event->x, event->y, &s, &e);
  1185.   if ( e != -1 )
  1186.     SelectSomething( s, e );
  1187.   if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  1188. }
  1189.  
  1190. /*************************************************************************
  1191.  *  fbInitTriStrip - initialze and reinit tristrip inster dynamics.
  1192.  *
  1193.  * if we are working on a tristrip, then start the next point. Otherwise,
  1194.  *  we are just drawing a line!
  1195.  */
  1196. static void fbInitTriStrip( XButtonPressedEvent *event )
  1197. {
  1198.   if (theTriStripCount) {
  1199.     if (theTriStripCount == TRIMAX) {
  1200.       fbFinishTriStrip( event );
  1201.       return;
  1202.     }
  1203.     theAnchorX = theAltX;
  1204.     theAnchorY = theAltY;
  1205.     theAltX = theDynX;
  1206.     theAltY = theDynY;
  1207.     theDynX = event->x;
  1208.     theDynY = event->y;
  1209.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1210.         theAnchorX, theAnchorY, theDynX, theDynY );
  1211.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1212.         theAltX, theAltY, theDynX, theDynY );
  1213.   } else {
  1214.     theAnchorX = event->x;
  1215.     theAnchorY = event->y;
  1216.     theDynX = event->x;
  1217.     theDynY = event->y;
  1218.     theAltX = event->x;
  1219.     theAltY = event->y;
  1220.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1221.           theAnchorX, theAnchorY, theDynX, theDynY );
  1222.   }
  1223. }
  1224.  
  1225. static void fbDynTriStrip( XMotionEvent *event )
  1226. {
  1227.   if (theTriStripCount) {
  1228.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1229.         theAnchorX, theAnchorY, theDynX, theDynY );
  1230.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1231.         theAltX, theAltY, theDynX, theDynY );
  1232.     theDynX = event->x;
  1233.     theDynY = event->y;
  1234.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1235.         theAnchorX, theAnchorY, theDynX, theDynY );
  1236.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1237.         theAltX, theAltY, theDynX, theDynY );
  1238.   } else {
  1239.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1240.           theAnchorX, theAnchorY, theDynX, theDynY );
  1241.     theDynX = event->x;
  1242.     theDynY = event->y;
  1243.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1244.           theAnchorX, theAnchorY, theDynX, theDynY );
  1245.   }
  1246. }
  1247. static void fbEndTriStrip( XButtonReleasedEvent *event )
  1248. {
  1249.   if (theTriStripCount) {
  1250.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), 
  1251.           theDynGC, theAnchorX, theAnchorY, theDynX, theDynY );
  1252.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
  1253.           theDynGC, theAltX, theAltY, theDynX, theDynY );
  1254.     theDynX = event->x;
  1255.     theDynY = event->y;
  1256.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), 
  1257.           theDynGC, theAnchorX, theAnchorY, theDynX, theDynY );
  1258.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea),
  1259.           theDynGC, theAltX, theAltY, theDynX, theDynY );
  1260.     theTriPoints[theTriStripCount].x = (float)theDynX;
  1261.     theTriPoints[theTriStripCount].y = (float)theDynY;
  1262.     theTriPoints[theTriStripCount].z = theDepth;
  1263.     theTriStripCount++;
  1264.   } else {
  1265.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1266.           theAnchorX, theAnchorY, theDynX, theDynY );
  1267.     theDynX = event->x;
  1268.     theDynY = event->y;
  1269.     XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1270.           theAnchorX, theAnchorY, theDynX, theDynY );
  1271.     theTriPoints[0].x = (float)theAnchorX;
  1272.     theTriPoints[0].y = (float)theAnchorY;
  1273.     theTriPoints[0].z = theDepth;
  1274.     theTriPoints[1].x = (float)theDynX;
  1275.     theTriPoints[1].y = (float)theDynY;
  1276.     theTriPoints[1].z = theDepth;
  1277.     theTriStripCount = 2;
  1278.   }
  1279. }
  1280.  
  1281. static void fbFinishTriStrip ( XButtonReleasedEvent *event )
  1282. {
  1283.   Ppoint_list3 points;
  1284.  
  1285.   int i;
  1286.  
  1287.  
  1288.   if (theTriStripCount < 3) return;
  1289.  
  1290.   points.num_points = theTriStripCount;
  1291.   points.points = theTriPoints; /* count has equaled index so far... */
  1292.   MapPoints(thePHIGSWorkstation, &points );
  1293.   if ( points.num_points > 2 ) {
  1294.     if (theNewStrux == 0) {
  1295.       theNewStrux = 111;
  1296.       InitStrux(theNewStrux);
  1297.     }
  1298.     InsertTriStrip( theNewStrux, &points, 1 );
  1299.     if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  1300.   }
  1301.   theTriStripCount = 0;
  1302. }
  1303.  
  1304.  
  1305. /*************************************************************************
  1306.  *
  1307.  */
  1308. static void fbInitTranslate( XButtonPressedEvent *event )
  1309. {
  1310.   if ( theSelectedElement == -1 ) {
  1311.     printf("nothing selected\n");
  1312.     return;
  1313.   }
  1314.  
  1315.   theAnchorX = event->x;
  1316.   theAnchorY = event->y;
  1317.   theDynX = event->x;
  1318.   theDynY = event->y;
  1319.   XDrawPoint( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1320.         theAnchorX, theAnchorY );
  1321. }
  1322.  
  1323. static void fbEndTranslate( XButtonReleasedEvent *event ) 
  1324. {
  1325.   Ppoint_list3 points;
  1326.   Ppoint3 pl[2];
  1327.  
  1328.   if ( theSelectedElement == -1 ) {
  1329.     printf("nothing selected\n");
  1330.     return;
  1331.   }
  1332.  
  1333.   theDynX = event->x;
  1334.   theDynY = event->y;
  1335.   XDrawPoint( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1336.         theDynX, theDynY );
  1337.  
  1338.   points.points = pl;
  1339.  
  1340.   if (Map2Points(thePHIGSWorkstation, theAnchorX, theAnchorY, theDynX, theDynY,
  1341.          &points)) {
  1342.     TranslateSelected( &points );
  1343.     if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  1344.   }
  1345. }
  1346.  
  1347. /*************************************************************************
  1348.  *
  1349.  */
  1350. static void fbInitStretch( XButtonPressedEvent *event )
  1351. {
  1352.   int i, count;
  1353.   XPoint *points, *p;
  1354.   float dist, currentDist;
  1355.   int error;
  1356.  
  1357.   theSelectedIndex = -1;
  1358.  
  1359.   error = GetXPointsFromSelected(&count, &points);
  1360.   if (error) {
  1361.     printf("imagine a popup dialog... %d\n", error );
  1362.     return;
  1363.   }
  1364.  
  1365.   currentDist = MAXFLOAT;
  1366.  
  1367.   for (i = 0, p = points; i < count; i++, p++ ) {
  1368.     /* don't bother with divide, only relative dist counts */
  1369.     dist = (event->x - p->x)*(event->x - p->x) + 
  1370.            (event->y - p->y)*(event->y - p->y);
  1371.     if (dist < currentDist) {
  1372.       currentDist = dist;
  1373.       theSelectedIndex = i;
  1374.     }
  1375.   }
  1376.  
  1377.   if (theSelectedIndex == -1) return;
  1378.  
  1379.   if (theSelectedIndex > 0) {
  1380.     theAnchorX = points[theSelectedIndex-1].x;
  1381.     theAnchorY = points[theSelectedIndex-1].y;
  1382.   } else {
  1383.     theAnchorX = points[theSelectedIndex+1].x;
  1384.     theAnchorY = points[theSelectedIndex+1].y;
  1385.   }
  1386.   free(points); /* all done */
  1387.   
  1388.   theDynX = event->x;
  1389.   theDynY = event->y;
  1390.   XDrawLine( XtDisplay(theDrawingArea), XtWindow(theDrawingArea), theDynGC, 
  1391.         theAnchorX, theAnchorY, theDynX, theDynY );
  1392.  
  1393.   /*
  1394.    * O.K.  we're ready.
  1395.    */
  1396.   theMotionHandlerTable[2] = fbDynLine;
  1397. }
  1398.  
  1399. /*************************************************************************
  1400.  * fbEndStretch
  1401.  */
  1402. static void fbEndStretch( XButtonReleasedEvent *event )
  1403. {
  1404.   Ppoint_list3 points;
  1405.   Ppoint3 pl[1];
  1406.  
  1407.   points.points = pl;
  1408.  
  1409.   points.num_points = 1;
  1410.   points.points[0].x = (float)event->x;
  1411.   points.points[0].y = (float)event->y;
  1412.   points.points[0].z = theDepth;
  1413.   MapPoints(thePHIGSWorkstation, &points);
  1414.  
  1415.   if ( points.num_points == 1 ) {
  1416.     StretchSelected(&points);
  1417.     if (!theUQUMFlag) predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  1418.   }
  1419.   theMotionHandlerTable[2] = fbDummy;
  1420. }       
  1421.  
  1422. /*************************************************************************
  1423.  * motionHandler
  1424.  *
  1425.  * Registered for button motion, meaning when the mouse moves while the
  1426.  * button is down, this routine gets called. 
  1427.  */
  1428.  
  1429. static void motionHandler( Widget widget,  XtPointer unused,
  1430.               XMotionEvent *event,  Boolean *continue_to_dispatch )
  1431. {
  1432.   int button;
  1433.  
  1434.   if ( event->state == Button1MotionMask ) {
  1435.     button = 0;
  1436.   } else if ( event->state == Button2MotionMask ) {
  1437.     button = 1;
  1438.   } else if ( event->state == Button3MotionMask ) {
  1439.     button = 2;
  1440.   } else {
  1441.     printf("bad button for motion %x\n", event->state );
  1442.     return;
  1443.   }
  1444.  
  1445.   theMotionHandlerTable[button](event);
  1446.   
  1447.   *continue_to_dispatch = 1;  /* tells whether to call other dispatchers */
  1448. }
  1449.  
  1450. /*************************************************************************
  1451.  *
  1452.  * A P P L I C A T I O N    P R O C E D U R E S
  1453.  *
  1454.  *************************************************************************
  1455.  *
  1456.  * Still a little overlap with the selected object interactions.
  1457.  */
  1458.  
  1459.  
  1460. /*************************************************************************
  1461.  * TranslateSelected - translate whatever is selected by the given vector
  1462.  */
  1463. void
  1464. TranslateSelected( Ppoint_list3 *points )
  1465. {
  1466.   Pint error;
  1467.   Pelem_type eType;
  1468.   size_t eSize;
  1469.   Pelem_data *eData;
  1470.   float deltaX, deltaY, deltaZ;
  1471.   Ppoint3 *p;
  1472.   int i;
  1473.  
  1474.   if ( theSelectedElement == -1 ) return;
  1475.  
  1476.   deltaX = points->points[1].x - points->points[0].x;
  1477.   deltaY = points->points[1].y - points->points[0].y;
  1478.   deltaZ = points->points[1].z - points->points[0].z;
  1479.  
  1480.   popen_struct(theSelectedStrux);
  1481.   pset_elem_ptr(theSelectedElement+1); /* move to primitive */
  1482.  
  1483. /*
  1484.  * 
  1485.  */
  1486.   pinq_cur_elem_type_size( &error, &eType, &eSize );
  1487.   if (error != 0) {
  1488.     printf("can't inquire element type & size strux = %d, element = %d\n",
  1489.          theSelectedStrux, theSelectedElement);
  1490.     return;
  1491.   }
  1492.   if (eType == PELEM_POLYLINE3) {
  1493.     if (thePHIGSStore == (Pstore)0) {
  1494.       pcreate_store(&i, &thePHIGSStore);
  1495.       if ( i != 0 ) printf("trouble crating store %d\n", i);
  1496.     }
  1497.  
  1498.     pinq_cur_elem_content(thePHIGSStore, &error, &eData );
  1499.     if (error != 0) {
  1500.       printf("can't inquire element type & size strux = %d, element = %d\n",
  1501.          theSelectedStrux, theSelectedElement);
  1502.       return;
  1503.     }
  1504.  
  1505.     for (i = 0; i < eData->point_list3.num_points; i++ ) {
  1506.       eData->point_list3.points[i].x = eData->point_list3.points[i].x + deltaX;
  1507.       eData->point_list3.points[i].y = eData->point_list3.points[i].y + deltaY;
  1508.       eData->point_list3.points[i].z = eData->point_list3.points[i].z + deltaZ;
  1509.     }
  1510.     poffset_elem_ptr(1);
  1511.     ppolyline3(&eData->point_list3);
  1512.     ppolymarker3(&eData->point_list3);
  1513.     poffset_elem_ptr(-2);
  1514.     pdel_elem();
  1515.     pdel_elem();
  1516.   } else if (eType == PELEM_TRI_STRIP3_DATA) {
  1517.   } else {
  1518.     printf("imagine a Motif alarm! selecting unknown element type %d, %d\n",
  1519.        eType, eSize );
  1520.     return;
  1521.   }
  1522.  
  1523.   pclose_struct();
  1524.  
  1525. }
  1526.  
  1527. /*************************************************************************
  1528.  * StretchSelected
  1529.  */
  1530. StretchSelected(Ppoint_list3 *points)
  1531. {
  1532.   Pint error;
  1533.   Pelem_type eType;
  1534.   size_t eSize;
  1535.   Pelem_data *eData;
  1536.   int i;
  1537.   Ppoint_list3 pts;
  1538.  
  1539.   popen_struct(theSelectedStrux);
  1540.   pset_elem_ptr(theSelectedElement+1); /* it's selected so move up 1 */
  1541.   pinq_cur_elem_type_size( &error, &eType, &eSize );
  1542.   if (error != 0) {
  1543.     printf("can't inquire elem type&size error %d strux = %d, element = %d\n",
  1544.        error, theSelectedStrux, theSelectedElement);
  1545.     return (error);
  1546.   }
  1547.   if (thePHIGSStore == (Pstore)0) {
  1548.     pcreate_store(&i, &thePHIGSStore);
  1549.     if ( i != 0 ) printf("trouble crating store %d\n", i);
  1550.     return (900);
  1551.   }
  1552.  
  1553.   pinq_cur_elem_content(thePHIGSStore, &error, &eData );
  1554.   if (error != 0) {
  1555.     printf("can't inquire element content, error = %d\n", error );
  1556.     return (error);
  1557.   }
  1558.   pset_edit_mode(PEDIT_REPLACE);
  1559.  
  1560.   if (eType == PELEM_POLYLINE3) {
  1561.     if (theSelectedIndex < eData->point_list3.num_points) {
  1562.       eData->point_list3.points[theSelectedIndex] = points->points[0];
  1563.     }
  1564.     ppolyline3((Ppoint_list3 *)eData);
  1565.     poffset_elem_ptr(1);
  1566.     ppolymarker3((Ppoint_list3 *)eData);  /* got to move the fluvii, too */
  1567.   } else if (eType == PELEM_TRI_STRIP3_DATA) {
  1568.  
  1569.     /* should check to make sure there are no normals!!! */
  1570.     if (theSelectedIndex < eData->tsd3.nv) {
  1571.       eData->tsd3.vdata.points[theSelectedIndex] = points->points[0];
  1572.     }
  1573.  
  1574.     ptri_strip3_data(eData->tsd3.fflag, eData->tsd3.vflag, 
  1575.              eData->tsd3.colr_model, eData->tsd3.nv,
  1576.              (Pfacet_data_arr3 *)eData->tsd3.fdata.norms,
  1577.              (Pfacet_vdata_arr3 *)&eData->tsd3.vdata.points);
  1578.     poffset_elem_ptr(1);
  1579.     pts.num_points = eData->tsd3.nv;
  1580.     pts.points = eData->tsd3.vdata.points;
  1581.     ppolymarker3(&pts);
  1582.   } else {
  1583.     printf("imagine a Motif alarm! selecting unknown element type %d, %d\n",
  1584.        eType, eSize );
  1585.   }
  1586.   pclose_struct();
  1587.   pset_edit_mode(PEDIT_INSERT);
  1588. }
  1589.  
  1590. /*************************************************************************
  1591.  * PickSomething - returns structure and element, else element == -1
  1592.  */
  1593. void
  1594. PickSomething( long wkid, int x, int y, long *struxID, long *elem)
  1595. {
  1596.   Pescape_in_data pickData;
  1597.   Pescape_out_data *outData;
  1598.   int names[2];
  1599.   int i;
  1600.  
  1601.   printf("\n\n going to pick xcoords %d,%d\n",x,y);
  1602.  
  1603.   pickData.escape_in_u4.ws_id = wkid;
  1604.   pickData.escape_in_u4.point.x = x;
  1605.   pickData.escape_in_u4.point.y = y;
  1606.   pickData.escape_in_u4.ap_size = 5.0;
  1607.   pickData.escape_in_u4.order = PORDER_TOP_FIRST;
  1608.   pickData.escape_in_u4.depth = 10;
  1609.   pickData.escape_in_u4.pet = 1;
  1610.   pickData.escape_in_u4.echo_switch = PSWITCH_ECHO;
  1611.  
  1612.   pickData.escape_in_u4.echo_volume.x_min = 0.0;
  1613.   pickData.escape_in_u4.echo_volume.x_max = 999.0;    
  1614.   pickData.escape_in_u4.echo_volume.y_min = 0.0;;    
  1615.   pickData.escape_in_u4.echo_volume.y_max = 999.0;
  1616.   pickData.escape_in_u4.echo_volume.z_min = 0.0;
  1617.   pickData.escape_in_u4.echo_volume.z_max = 999.0;
  1618.  
  1619.   names[0] = 1;
  1620.   names[1] = 2;
  1621.   pickData.escape_in_u4.filter.incl_set.num_ints = 2;
  1622.   pickData.escape_in_u4.filter.incl_set.ints = names;
  1623.   pickData.escape_in_u4.filter.excl_set.num_ints = 0;
  1624.  
  1625.   if (thePHIGSStore == (Pstore)0) {
  1626.     pcreate_store(&i, &thePHIGSStore);
  1627.     if ( i != 0 ) printf("trouble crating store %d\n", i);
  1628.   }
  1629. /*
  1630.  * ignore DC check for echo area, pickData works iff wkid != 0
  1631.  * -4 is the programmatic pick.
  1632.  */
  1633.   pescape(-3, &pickData, thePHIGSStore, &outData );
  1634.   pescape(-4, &pickData, thePHIGSStore, &outData );
  1635.  
  1636.   if (outData->escape_out_u4.status == PIN_STATUS_OK) {
  1637.     Ppick_path_elem *pe;
  1638.  
  1639. /*printf(" we got one! path depth = %d\n",outData->escape_out_u4.pick.depth);
  1640.     pe = outData->escape_out_u4.pick.path_list;
  1641.     for (i=0;i<outData->escape_out_u4.pick.depth;i++, pe++) {
  1642.       printf(" level %d >> structure ID %d, pick_id %d, element_id %d\n",
  1643.          i, pe->struct_id, pe->pick_id, pe->elem_pos );
  1644.     }
  1645. */
  1646.     *struxID = outData->escape_out_u4.pick.path_list[outData->escape_out_u4.pick.depth-1].struct_id;
  1647.     *elem = outData->escape_out_u4.pick.path_list[outData->escape_out_u4.pick.depth-1].elem_pos;
  1648. /*    printf("that's all\n"); */
  1649.   } else {
  1650.     printf(" no pick, getta life\n");
  1651.     *elem = -1;
  1652.   }
  1653. }
  1654.  
  1655. /*************************************************************************
  1656.  *  SelectSomething( long strux, long element )
  1657.  *
  1658.  */
  1659. void SelectSomething( long strux, long element )
  1660. {
  1661.   Pint error;
  1662.   Pelem_type eType;
  1663.   size_t eSize;
  1664.   Pelem_data *eData;
  1665.   int i;
  1666.   Ppoint_list3 points;
  1667.  
  1668.   popen_struct(strux);
  1669.   pset_elem_ptr(element);
  1670.   pinq_cur_elem_type_size( &error, &eType, &eSize );
  1671.   if (error != 0) {
  1672.     printf("can't inquire element type & size strux = %d, element = %d\n",
  1673.        strux, element);
  1674.     return;
  1675.   }
  1676.   if (thePHIGSStore == (Pstore)0) {
  1677.     pcreate_store(&i, &thePHIGSStore);
  1678.     if ( i != 0 ) printf("trouble crating store %d\n", i);
  1679.   }
  1680.   if (eType == PELEM_POLYLINE3) {
  1681.     pinq_cur_elem_content(thePHIGSStore, &error, &eData );
  1682.     if (error != 0) {
  1683.       printf("can't inquire element type & size strux = %d, element = %d\n",
  1684.          strux, element);
  1685.       return;
  1686.     }
  1687.  
  1688.     ppolymarker3((Ppoint_list3 *)eData);
  1689.     poffset_elem_ptr(-2);
  1690.     pset_line_colr_ind(SELECT_COLOR_IND);
  1691.     pclose_struct();
  1692.   } else if (eType == PELEM_TRI_STRIP3_DATA) {
  1693.     pinq_cur_elem_content(thePHIGSStore, &error, &eData );
  1694.     if (error != 0) {
  1695.       printf("can't inquire element type & size strux = %d, element = %d\n",
  1696.          strux, element);
  1697.       return;
  1698.     }
  1699.     /* should check to make sure there are no normals!!! */
  1700.     points.num_points = eData->tsd3.nv;
  1701.     points.points = eData->tsd3.vdata.points;
  1702.     ppolymarker3(&points);
  1703.     poffset_elem_ptr(-2);
  1704.     pset_int_colr_ind(SELECT_COLOR_IND);
  1705.     pclose_struct();
  1706.   } else {
  1707.     printf("imagine a Motif alarm! selecting unknown element type %d, %d\n",
  1708.        eType, eSize );
  1709.     pclose_struct();
  1710.     return;
  1711.   }
  1712.  
  1713.   theSelectedStrux = strux;
  1714.   theSelectedElement = element;
  1715. }
  1716.  
  1717. /*************************************************************************
  1718.  * ClearSelection
  1719.  *
  1720.  * Implicitly knows that each element has a color followed by a primitive
  1721.  *  - color
  1722.  *  - primitive
  1723.  *  
  1724.  * The selected Element has an extra color between the color & prim and 
  1725.  * the point primitive directly afterwords.  Two extra elements.  This
  1726.  * will be a headache if multiple elements are allowed to be selected.
  1727.  *
  1728.  *  - color
  1729.  *  - select color
  1730.  *  - primitive
  1731.  *  - points.
  1732.  *
  1733.  * The selected color is really at theSelectedElement. Set the pointer and 
  1734.  * delete it. The element pointer moves forward.  Skip two elements and 
  1735.  * delete the points.
  1736.  *
  1737.  */
  1738. void ClearSelection()
  1739. {
  1740.   if ( theSelectedElement == -1 ) return;
  1741.  
  1742.   popen_struct(theSelectedStrux);
  1743.   pset_elem_ptr(theSelectedElement);
  1744.   pdel_elem();
  1745.   poffset_elem_ptr(2);
  1746.   pdel_elem();
  1747.   pclose_struct();
  1748.  
  1749.   theSelectedStrux = -1;
  1750.   theSelectedElement= -1;
  1751.  
  1752. }
  1753.  
  1754. /*************************************************************************
  1755.  * DeleteSelected
  1756.  */
  1757. void DeleteSelected()
  1758. {
  1759.   if ( theSelectedElement == -1 ) return;
  1760.  
  1761.   popen_struct(theSelectedStrux);
  1762.   pdel_elem_range(theSelectedElement-1, theSelectedElement+2);
  1763.   pclose_struct();
  1764.  
  1765.   theSelectedStrux = -1;
  1766.   theSelectedElement= -1;
  1767.  
  1768. }
  1769.  
  1770. /*************************************************************************
  1771.  * InitStrux
  1772.  */
  1773. void InitStrux( long strux )
  1774. {
  1775.   Pint_list names;
  1776.   int int_array[2];
  1777.   Pint error;
  1778.   Pmatrix3 matrix;
  1779.   Prefl_props reflProps;
  1780.  
  1781.   ppost_struct(thePHIGSWorkstation, strux, 0.0);
  1782.   popen_struct(strux);
  1783.   /*
  1784.    * need this for picking
  1785.    */
  1786.   names.num_ints = 2;
  1787.   names.ints = int_array;
  1788.   names.ints[0] = 2;
  1789.   names.ints[1] = 1;
  1790.   padd_names_set(&names);
  1791.  
  1792.   pset_view_ind(1);
  1793.  
  1794.   pset_int_style(PSTYLE_HOLLOW);       /* INT_STYLE_ELEM == element 3 */
  1795.   pset_refl_eqn(PREFL_AMB_DIFF_SPEC);  /* REFL_EQN_ELEM  == element 4 */
  1796.  
  1797.   /* set the area properties */
  1798.   reflProps.ambient_coef = 0.3;    /* ambient coefficient */
  1799.   reflProps.diffuse_coef = 0.3;    /* diffuse coefficient */
  1800.   reflProps.specular_coef = 0.7;    /* specular coefficient */
  1801.   /* set specular color to white */
  1802.   reflProps.specular_colr.type = PMODEL_RGB;    /* specular color model */
  1803.   reflProps.specular_colr.val.general.x = 1.0;
  1804.   reflProps.specular_colr.val.general.y = 1.0;
  1805.   reflProps.specular_colr.val.general.z = 1.0;
  1806.   reflProps.specular_exp = 50.0;    /* specular exponent */
  1807.  
  1808.   pset_refl_props(&reflProps);
  1809.   pset_int_shad_meth(PSD_NONE);        /* INT_SHAD_ELEM  == element */
  1810.   theLightsON.num_ints = 2;
  1811.   theLightsON.ints[0] = 1;
  1812.   theLightsON.ints[1] = 2;
  1813.   theLightsOFF.num_ints = 0;
  1814.   pset_light_src_state(&theLightsON, &theLightsOFF); /* LIGHT_SRC_ELEM 6 */
  1815.   protate_x(0.0, &error, matrix);
  1816.   pset_local_tran3(matrix, PTYPE_REPLACE); /* MATRIX_ELEM 7 */
  1817.  
  1818.   pset_face_cull_mode( PCULL_NONE );
  1819.  
  1820.   pclose_struct();
  1821. }
  1822.  
  1823. /*************************************************************************
  1824.  * InsertLine
  1825.  */
  1826. void InsertLine( long strux, Ppoint_list3 *points, int select )
  1827. {
  1828.   Pint error, e;
  1829.  
  1830.   if ( theSelectedElement != -1 ) ClearSelection();
  1831.  
  1832. /*   pset_edit_mode(PEDIT_INSERT); */
  1833.   popen_struct(strux);
  1834.   pset_line_colr_ind(theCurrentLineIndex);
  1835.   ppolyline3(points);
  1836.  
  1837.   if (select) {
  1838.     pinq_elem_ptr( &error, &e );
  1839.     pclose_struct();
  1840.     SelectSomething( strux, e );
  1841.   } else {
  1842.     pclose_struct();
  1843.   }
  1844. }
  1845.  
  1846. /*************************************************************************
  1847.  * InsertTriStrip
  1848.  */
  1849. void InsertTriStrip( long strux, Ppoint_list3 *points, int select )
  1850. {
  1851.   Pint error, e;
  1852.   Pfacet_vdata_arr3 vData;
  1853.  
  1854.   if ( theSelectedElement != -1 ) ClearSelection();
  1855.  
  1856.   popen_struct(strux);
  1857.   pset_int_colr_ind(theCurrentLineIndex);
  1858.   vData.points = points->points;
  1859.   ptri_strip3_data(PFACET_NONE, PVERT_COORD, PMODEL_RGB, points->num_points,
  1860.           (Pfacet_data_arr3 *)0, &vData);
  1861.  
  1862.   if (select) {
  1863.     pinq_elem_ptr( &error, &e );
  1864.     pclose_struct();
  1865.     SelectSomething( strux, e );
  1866.   } else {
  1867.     pclose_struct();
  1868.   }
  1869. }
  1870.  
  1871. /*************************************************************************
  1872.  * MapPoints 
  1873.  */
  1874. int
  1875. MapPoints( int wkid, Ppoint_list3 *points )
  1876. {
  1877.   Pescape_in_data pickData;
  1878.   Pescape_out_data *outData;
  1879.   int i, count;
  1880.  
  1881.   count = points->num_points;
  1882.  
  1883.   pickData.escape_in_u5.ws_id = wkid;
  1884.   pickData.escape_in_u5.points = *points;
  1885.  
  1886.   if (thePHIGSStore == (Pstore)0) {
  1887.     pcreate_store(&i, &thePHIGSStore);
  1888.     if ( i != 0 ) printf("trouble crating store %d\n", i);
  1889.   }
  1890.  
  1891. /*
  1892.  * ignore DC check for echo area, pickData works iff wkid != 0
  1893.   pescape(-3, &pickData, thePHIGSStore, &outData );
  1894.  */
  1895.  
  1896.   pescape(-5, &pickData, thePHIGSStore, &outData );
  1897.  
  1898.   if ( outData->escape_out_u5.points.num_points != count ) {
  1899.     printf("need %d points, got %d\n",
  1900.        count, outData->escape_out_u5.points.num_points);
  1901.   }
  1902.  
  1903.   for (i= 0; i<outData->escape_out_u5.points.num_points; i++ ) {
  1904.     points->points[i] = outData->escape_out_u5.points.points[i];
  1905.   }
  1906.  
  1907.   points->num_points = outData->escape_out_u5.points.num_points;
  1908.   return (1);
  1909. }
  1910.  
  1911. /*************************************************************************
  1912.  * Map2Points 
  1913.  */
  1914. int
  1915. Map2Points( int wkid, int firstX, int firstY, int secondX, int secondY,
  1916.        Ppoint_list3 *points )
  1917. {
  1918.   Pescape_in_data pickData;
  1919.   Pescape_out_data *outData;
  1920.   int i;
  1921.  
  1922.   points->num_points = 2;
  1923.   points->points[0].x = (float)firstX;
  1924.   points->points[0].y = (float)firstY;
  1925.   points->points[0].z = theDepth;
  1926.   points->points[1].x = (float)secondX;
  1927.   points->points[1].y = (float)secondY;
  1928.   points->points[1].z = theDepth;
  1929.  
  1930.   pickData.escape_in_u5.ws_id = wkid;
  1931.   pickData.escape_in_u5.points = *points;
  1932.  
  1933.   if (thePHIGSStore == (Pstore)0) {
  1934.     pcreate_store(&i, &thePHIGSStore);
  1935.     if ( i != 0 ) printf("trouble crating store %d\n", i);
  1936.   }
  1937.  
  1938. /*
  1939.  * ignore DC check for echo area, pickData works iff wkid != 0
  1940.   pescape(-3, &pickData, thePHIGSStore, &outData );
  1941.  */
  1942.  
  1943.   pescape(-5, &pickData, thePHIGSStore, &outData );
  1944.  
  1945.   if ( outData->escape_out_u5.points.num_points != 2 ) {
  1946.     printf("need 2 points, got %d\n", outData->escape_out_u5.points.num_points);
  1947.     return (0);
  1948.   }
  1949.  
  1950.   points->num_points = 2;
  1951.   points->points[0] = outData->escape_out_u5.points.points[0];
  1952.   points->points[1] = outData->escape_out_u5.points.points[1];
  1953.   
  1954.   return (1);
  1955. }
  1956.  
  1957. /*************************************************************************
  1958.  * MapWcPointsToX
  1959.  *
  1960.  * TODO:
  1961.  */
  1962. static int
  1963. MapWcPointsToX( int wkid, int view, Ppoint_list3 *wcPoints, XPoint *xPoints )
  1964. {
  1965.   Ppoint3 p, q;
  1966.   int i, count;
  1967.   Pint error;
  1968.   Pupd_st update_state;
  1969.   Pview_rep3 curRep, reqRep;
  1970.   Pmatrix3 orient, mapping;
  1971.   Plimit3     req_win_lim, cur_win_lim;
  1972.   Plimit3     req_vp_lim,   cur_vp_lim;
  1973.   float winWidth, winHeight, winX, winY, XX, XY;
  1974.   XPoint *xp = xPoints;
  1975.   float scale;
  1976.  
  1977.   count = wcPoints->num_points;
  1978.  
  1979.   /*
  1980.    * since we do not leave view information hanging around as requested
  1981.    * we won't worry about whether ther is an update pending. Just use
  1982.    * the current information.
  1983.    */
  1984. /* BUG!!!
  1985.  *  XSync(XtDisplay(theDrawingArea), 1);
  1986.  *  pinq_view_rep( wkid, view, &error, &update_state, &curRep, &reqRep);
  1987.  *  if (error) return ((int)error);
  1988.  *  bcopy( (char *)&curRep.ori_matrix, (char *)&orient, sizeof(Pmatrix3));
  1989.  * bcopy( (char *)&curRep.map_matrix, (char *)&mapping, sizeof(Pmatrix3));
  1990.  */
  1991.   /*
  1992.    * We rely on the fact that we always use the whole window for the
  1993.    * Workstation viewport.  Get the information we want, incase this
  1994.    * scratch area gets creamed.
  1995.    */
  1996.   pinq_ws_tran3( wkid, &error, &update_state, &req_win_lim, &cur_win_lim,
  1997.         &req_vp_lim, &cur_vp_lim);
  1998.   if (error) return ((int)error);
  1999.  
  2000.   winWidth = cur_win_lim.x_max - cur_win_lim.x_min;
  2001.   winHeight = cur_win_lim.y_max - cur_win_lim.y_min;
  2002.   winX = cur_win_lim.x_min;
  2003.   winY = cur_win_lim.y_min;
  2004.   XX = cur_vp_lim.x_max;
  2005.   XY = cur_vp_lim.y_max;
  2006.  
  2007.   /*
  2008.    * since we always maintain the workstation window and workstation viewport
  2009.    * "similar" in the geometry sense, they are always isotropic. So, either
  2010.    * XX/width or XY/height should be the same.
  2011.    */
  2012.   scale = XX/winWidth;
  2013.  
  2014.   for (i = 0; i < count; i++, xp++ ) {
  2015.     ptran_point3(&wcPoints->points[i], theMatOri, &error,  &q );
  2016.     if (error) return (error);
  2017.     ptran_point3(&q, theMatMap, &error,  &p );
  2018.     if (error) return (error);
  2019.     
  2020.     /* OK, got an NPC point. take it to X. */
  2021.     xp->x = (p.x - winX) * scale;
  2022.     xp->y = XY - ((p.y - winY) * scale);
  2023.   }
  2024.   return (0);
  2025. }
  2026.  
  2027. /*************************************************************************
  2028.  *  GetXPointsFromSelected
  2029.  *
  2030.  *  generate X coordinates for each vertex of the selected object.
  2031.  *   - inquire element contents
  2032.  *   - map from world [should be model] to screen using MapWCPointsToX
  2033.  *
  2034.  * ALLOCATES points array.
  2035.  */
  2036. static int GetXPointsFromSelected(int *count, XPoint **points)
  2037. {
  2038.   Pint error;
  2039.   Pelem_type eType;
  2040.   size_t eSize;
  2041.   Pelem_data *eData;
  2042.   int i;
  2043.   Ppoint_list3 wcPoints, *p;
  2044.  
  2045.   *count = 0;
  2046.  
  2047.   popen_struct(theSelectedStrux);
  2048.   pset_elem_ptr(theSelectedElement+1); /* it's selected so move up 1 */
  2049.   pinq_cur_elem_type_size( &error, &eType, &eSize );
  2050.   if (error != 0) {
  2051.     printf("can't inquire elem type&size error %d strux = %d, element = %d\n",
  2052.        error, theSelectedStrux, theSelectedElement);
  2053.     return (error);
  2054.   }
  2055.   if (thePHIGSStore == (Pstore)0) {
  2056.     pcreate_store(&i, &thePHIGSStore);
  2057.     if ( i != 0 ) printf("trouble crating store %d\n", i);
  2058.     return (900);
  2059.   }
  2060.  
  2061.   pinq_cur_elem_content(thePHIGSStore, &error, &eData );
  2062.   pclose_struct();
  2063.   if (error != 0) {
  2064.     printf("can't inquire element content, error = %d\n", error );
  2065.     return (error);
  2066.   }
  2067.   
  2068.   if (eType == PELEM_POLYLINE3) {
  2069.     wcPoints.num_points = eData->point_list3.num_points;
  2070.     wcPoints.points = eData->point_list3.points;
  2071.   } else if (eType == PELEM_TRI_STRIP3_DATA) {
  2072.     wcPoints.num_points = eData->tsd3.nv;
  2073.     wcPoints.points = eData->tsd3.vdata.points;
  2074.   } else {
  2075.     printf("trying to get points from unknown element\n");
  2076.   }
  2077.  
  2078.   *points = (XPoint *)malloc(wcPoints.num_points*sizeof(XPoint));
  2079.   if (!*points) return (900);
  2080.   /*
  2081.    * back translate these from model to world!! Just ruined our copy.
  2082.    * No we're not doing that yet.
  2083.    */
  2084.   if (error = MapWcPointsToX(thePHIGSWorkstation, 1, &wcPoints, *points ))
  2085.     return (error);
  2086.  
  2087.   *count = wcPoints.num_points;
  2088.   return (0);
  2089. }
  2090.  
  2091. /*************************************************************************
  2092.  * applyViewSet - get values from widget and set the view representation
  2093.  */
  2094. static int applyViewSet(int viewNumber)
  2095. {
  2096.   Ppoint3 vrp;
  2097.   Pvec3 vpn;
  2098.   Pvec3 vup;
  2099.   
  2100.   Pview_rep3 vrep;                           /*  view structure */
  2101.   
  2102.   Pint err;
  2103.   Pview_map3 view_map;
  2104.  
  2105.   int persp;
  2106.   MrmCode class;
  2107.  
  2108.   if (theViewForm == NULL) {     /* The first time, fetch order box. */
  2109.     if (MrmFetchWidget(theMrmHierarchy, "view_set_dialog", theTopLevel,
  2110.                &theViewForm, &class) != MrmSUCCESS) {
  2111.       printf("can't fetch view set dialog");
  2112.       return;
  2113.     }
  2114.   }
  2115.  
  2116.   
  2117.   /* View Reference Point */
  2118.   if (getNumberWidgetValue(k_view_ref_pt_x, &vrp.x)) return(1);
  2119.   if (getNumberWidgetValue(k_view_ref_pt_y, &vrp.y)) return(1);
  2120.   if (getNumberWidgetValue(k_view_ref_pt_z, &vrp.z)) return(1);
  2121.  
  2122.   /* view plane normal */
  2123.   if (getNumberWidgetValue(k_view_pl_norm_x, &vpn.delta_x)) return(1);
  2124.   if (getNumberWidgetValue(k_view_pl_norm_y, &vpn.delta_y)) return(1);
  2125.   if (getNumberWidgetValue(k_view_pl_norm_z, &vpn.delta_z)) return(1);
  2126.  
  2127.   /*  view up vector */
  2128.   if (getNumberWidgetValue(k_view_up_vect_x, &vup.delta_x)) return(1);
  2129.   if (getNumberWidgetValue(k_view_up_vect_y, &vup.delta_y)) return(1);
  2130.   if (getNumberWidgetValue(k_view_up_vect_z, &vup.delta_z)) return(1);
  2131.   
  2132.   peval_view_ori_matrix3( &vrp, &vpn, &vup, 
  2133.              &err, vrep.ori_matrix);
  2134.   
  2135.   if (err != 0) { printf( "view orientation error %d\n",err); return (1); }
  2136.  
  2137.   if (getNumberWidgetValue(k_proj_ref_pt_x, &view_map.proj_ref_point.x)) return (1);
  2138.   if (getNumberWidgetValue(k_proj_ref_pt_y, &view_map.proj_ref_point.y)) return (1);
  2139.   if (getNumberWidgetValue(k_proj_ref_pt_z, &view_map.proj_ref_point.z)) return (1);
  2140.   if (getNumberWidgetValue(k_view_window_minx, &view_map.win.x_min)) return (1);
  2141.   if (getNumberWidgetValue(k_view_window_maxx, &view_map.win.x_max)) return (1);
  2142.   if (getNumberWidgetValue(k_view_window_miny, &view_map.win.y_min)) return (1);
  2143.   if (getNumberWidgetValue(k_view_window_maxy, &view_map.win.y_max)) return (1);
  2144.   if (getNumberWidgetValue(k_view_plane_dist, &view_map.view_plane)) return (1);
  2145.   if (getNumberWidgetValue(k_view_plane_back, &view_map.back_plane)) return (1);
  2146.   if (getNumberWidgetValue(k_view_plane_front, &view_map.front_plane)) return (1);
  2147.   if (getNumberWidgetValue(k_proj_vp_minx, &view_map.proj_vp.x_min)) return (1);
  2148.   if (getNumberWidgetValue(k_proj_vp_maxx, &view_map.proj_vp.x_max)) return (1);
  2149.   if (getNumberWidgetValue(k_proj_vp_miny, &view_map.proj_vp.y_min)) return (1);
  2150.   if (getNumberWidgetValue(k_proj_vp_maxy, &view_map.proj_vp.y_max)) return (1);
  2151.   if (getNumberWidgetValue(k_proj_vp_minz, &view_map.proj_vp.z_min)) return (1);
  2152.   if (getNumberWidgetValue(k_proj_vp_maxz, &view_map.proj_vp.z_max)) return (1);
  2153.   if (widgetArray[k_proj_type_persp] == NULL) {
  2154.       /* The first time, fetch order box. */
  2155.       if (MrmFetchWidget(theMrmHierarchy, numberStrings[k_proj_type_persp],
  2156.                          theTopLevel, &widgetArray[k_proj_type_persp],
  2157.              &class) != MrmSUCCESS) {
  2158.     printf("can't fetch number perspective\n");
  2159.     return (1);
  2160.       }
  2161.     }
  2162.  
  2163.   /* View Reference Point */
  2164.   persp = XmToggleButtonGetState(widgetArray[k_proj_type_persp]);
  2165.  
  2166.   if (persp) {
  2167.     view_map.proj_type = PTYPE_PERSPECT;  
  2168.   } else {
  2169.     view_map.proj_type = PTYPE_PARAL;
  2170.   }
  2171.  
  2172.   peval_view_map_matrix3( &view_map, &err, vrep.map_matrix);
  2173.   
  2174.   if (err != 0) { printf( "view mapping error %d\n",err); return (1); }
  2175.   
  2176.   vrep.clip_limit =  view_map.proj_vp;
  2177.   vrep.xy_clip = PIND_CLIP;
  2178.   vrep.back_clip = PIND_CLIP;
  2179.   vrep.front_clip = PIND_CLIP;
  2180.   pset_view_rep3( thePHIGSWorkstation, viewNumber, &vrep);
  2181.  
  2182.   bcopy( (char *)&vrep.ori_matrix, (char *)&theMatOri, sizeof(Pmatrix3));
  2183.   bcopy( (char *)&vrep.map_matrix, (char *)&theMatMap, sizeof(Pmatrix3));
  2184.  
  2185.   predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  2186.  
  2187.   return (0);
  2188.  
  2189. }
  2190.  
  2191. /*************************************************************************
  2192.  * getNumberWidgetValue - get a number from a string widget.
  2193.  */
  2194. static int getNumberWidgetValue(int id, float *value)
  2195. {
  2196.   double number;
  2197.   char *text, *notText;
  2198.   MrmCode class;
  2199.  
  2200.   if (id > numberStringCount) return (1);
  2201.  
  2202.   if (widgetArray[id] == NULL) {     /* The first time, fetch order box. */
  2203.       if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
  2204.              &widgetArray[id], &class) != MrmSUCCESS) {
  2205.     printf("can't fetch number %d\n",id);
  2206.     return (1);
  2207.       }
  2208.     }
  2209.  
  2210.   /* View Reference Point */
  2211.   XtVaGetValues(widgetArray[id], XmNvalue, &text, NULL);
  2212.  
  2213.   number = strtod(text,¬Text);
  2214.   if (number == 0.0 && text == notText) {
  2215.     printf(" could get a number %s, %s\n",numberStrings[id],text);
  2216.     return (1);
  2217.   }
  2218.  
  2219.   *value = (float) number;
  2220.   return (0);
  2221. }
  2222.  
  2223. /*************************************************************************
  2224.  * getWidgetValue - get a number from a string widget.
  2225.  */
  2226. static int getWidgetValue(int id, float *value)
  2227. {
  2228.   double number;
  2229.   char *text, *notText;
  2230.   MrmCode class;
  2231.   int intVal, i;
  2232.   short decVal;
  2233.   
  2234.  
  2235.   if (id > numberStringCount) return (1);
  2236.  
  2237.   if (widgetArray[id] == NULL) {     /* The first time, fetch order box. */
  2238.       if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
  2239.              &widgetArray[id], &class) != MrmSUCCESS) {
  2240.     printf("can't fetch number %d\n",id);
  2241.     return (1);
  2242.       }
  2243.     }
  2244.  
  2245.   /* View Reference Point */
  2246.   XtVaGetValues(widgetArray[id],
  2247.         XmNvalue, &intVal, 
  2248.         XmNdecimalPoints, &decVal,
  2249.         NULL);
  2250.  
  2251.   number = (double)intVal;
  2252.  
  2253.   for (i = 0; i < (int)decVal; i++ ) number = number / 10.0;
  2254.  
  2255. /*  printf ("getWidgetValue %d, %d, %d, %g\n", id, intVal, decVal, number); */
  2256.  
  2257.   *value = (float) number;
  2258.   return (0);
  2259. }
  2260.  
  2261. /*************************************************************************
  2262.  * setNumberWidgetValue - set a number into a string widget.
  2263.  */
  2264. static int setNumberWidgetValue(int id, float value)
  2265. {
  2266.   double number;
  2267.   char text[80];
  2268.   MrmCode class;
  2269.   Arg al[1];
  2270.     
  2271.   if (id > numberStringCount) return (1);
  2272.  
  2273.   if (widgetArray[id] == NULL) {     /* The first time, fetch order box. */
  2274.       if (MrmFetchWidget(theMrmHierarchy, numberStrings[id], theTopLevel,
  2275.              &widgetArray[id], &class) != MrmSUCCESS) {
  2276.     printf("can't fetch number %d\n",id);
  2277.     return (1);
  2278.       }
  2279.     }
  2280.  
  2281.   sprintf(text, "%1.6f", value);
  2282.  
  2283.   XtSetArg(al[0],  XmNvalue, text );
  2284.   XtSetValues(widgetArray[id], al, 1);
  2285.  
  2286.   return (0);
  2287. }
  2288.  
  2289. /*************************************************************************
  2290.  * DumpStrux
  2291.  *
  2292.  * In: strux   - structure to dump
  2293.  *     element - is -1 do whole structure, else just that one
  2294.  *     pretty  - use pretty formatting, dump into Motif window???
  2295.  */
  2296. void
  2297. DumpStrux( long strux, long element, int pretty )
  2298. {
  2299.   int i;
  2300.   Pint errind;
  2301.   Pelem_data *data;
  2302.   Pelem_type eType;
  2303.   size_t eSize;
  2304.  
  2305.   if (thePHIGSStore == (Pstore)0) {
  2306.     pcreate_store(&i, &thePHIGSStore);
  2307.     if ( i != 0 ) printf("trouble crating store %d\n", i);
  2308.   }
  2309.  
  2310.   if (element != -1) {
  2311.     pinq_elem_type_size(strux,element,&errind,&eType,&eSize);
  2312.     if (errind != 0) return;
  2313.     pinq_elem_content(strux, element, thePHIGSStore, &errind, &data );
  2314.     if (errind != 0) return;
  2315.     PrintElement( strux, element, eType, (long)eSize, data );
  2316.   } else {
  2317.     errind = 0;
  2318.     for (i = 1; errind == 0; i++ ) {
  2319.       pinq_elem_type_size(strux,i,&errind,&eType,&eSize);
  2320.       if (errind != 0) return;
  2321.       pinq_elem_content(strux, i, thePHIGSStore, &errind, &data );
  2322.       if (errind != 0) return;
  2323.       PrintElement( strux, i, eType, (long)eSize, data );
  2324.     }
  2325.   }
  2326. }
  2327.  
  2328. /*************************************************************************
  2329.  * PrintElement - dump out the element contents in hex.
  2330.  */
  2331. void
  2332. PrintElement( long struxID, long element, Pelem_type eType, long eSize,
  2333.          Pelem_data *data )
  2334. {
  2335.   long i, *p;
  2336. static char *mnemonics[] = {
  2337. "ALL", "NIL", "POLYLINE3", "POLYLINE", "POLYMARKER3",
  2338. "POLYMARKER", "TEXT3", "TEXT", "ANNO_TEXT_REL3", "ANNO_TEXT_REL",
  2339. "FILL_AREA3", "FILL_AREA", "FILL_AREA_SET3", "FILL_AREA_SET", "CELL_ARRAY3",
  2340. "CELL_ARRAY", "GDP3", "GDP", "LINE_IND", "MARKER_IND",
  2341. "TEXT_IND", "INT_IND", "EDGE_IND", "LINETYPE", "LINEWIDTH",
  2342. "LINE_COLR_IND", "MARKER_TYPE", "MARKER_SIZE", "MARKER_COLR_IND", "TEXT_FONT",
  2343. "TEXT_PREC", "CHAR_EXPAN", "CHAR_SPACE", "TEXT_COLR_IND", "CHAR_HT",
  2344. "CHAR_UP_VEC", "TEXT_PATH", "TEXT_ALIGN", "ANNO_CHAR_HT", "ANNO_CHAR_UP_VEC",
  2345. "ANNO_PATH", "ANNO_ALIGN", "ANNO_STYLE", "INT_STYLE", "INT_STYLE_IND",
  2346. "INT_COLR_IND", "EDGE_FLAG", "EDGETYPE", "EDGEWIDTH", "EDGE_COLR_IND",
  2347. "PAT_SIZE", "PAT_REF_POINT_VECS", "PAT_REF_POINT", "ADD_NAMES_SET", 
  2348. "REMOVE_NAMES_SET",
  2349. "INDIV_ASF", "HLHSR_ID", "LOCAL_MODEL_TRAN3", "LOCAL_MODEL_TRAN", 
  2350. "GLOBAL_MODEL_TRAN3",
  2351. "GLOBAL_MODEL_TRAN", "MODEL_CLIP_VOL3", "MODEL_CLIP_VOL", "MODEL_CLIP_IND", 
  2352. "RESTORE_MODEL_CLIP_VOL",
  2353. "VIEW_IND", "EXEC_STRUCT", "LABEL", "APPL_DATA", "GSE",
  2354. "PICK_ID", "POLYLINE_SET3_DATA", "FILL_AREA_SET3_DATA", "TRI_STRIP3_DATA", 
  2355. "QUAD_MESH3_DATA",
  2356. "SET_OF_FILL_AREA_SET3_DATA", "NUNI_BSP_CURVE", "NUNI_BSP_SURF", 
  2357. "CELL_ARRAY3_PLUS", "TEXT_COLR",
  2358. "MARKER_COLR", "EDGE_COLR", "LINE_COLR", "CURVE_APPROX_CRIT", "LINE_SHAD_METH",
  2359. "INT_COLR", "BACK_INT_COLR", "BACK_INT_STYLE", "BACK_INT_STYLE_IND", 
  2360. "REFL_PROPS",
  2361. "BACK_REFL_PROPS", "INT_SHAD_METH", "BACK_INT_SHAD_METH", "INT_REFL_EQN", 
  2362. "BACK_INT_REFL_EQN",
  2363. "SURF_APPROX_CRIT", "PARA_SURF_CHARACS", "FACE_DISTING_MODE", "FACE_CULL_MODE",
  2364. "LIGHT_SRC_STATE", "DCUE_IND", "COLR_MAP_IND", "RENDERING_COLR_MODEL"
  2365. };
  2366.  
  2367.   printf("\n strux %d, element %d, type_no %d, size = %d mnemonic = %s\n",
  2368.      struxID, element, (int)eType, eSize, mnemonics[(int)eType] );
  2369.   p = (long *)data;
  2370.   if (eSize == 0) {
  2371.     if (eType == PELEM_LOCAL_MODEL_TRAN3) {
  2372.     for (i = 0; i < 16; i++, p++ ){
  2373.       if ((i&0x7) == 7) printf("\n");
  2374.       printf(" %x,", *p);
  2375.     }}        
  2376.   } else {
  2377.     for (i = 0; i < (eSize>>2); i++, p++ ){
  2378.       if ((i&0x7) == 7) printf("\n");
  2379.       printf(" %x,", *p);
  2380.     }
  2381.   }
  2382. }
  2383.  
  2384. /*************************************************************************
  2385.  * ResizeWorkstation
  2386.  *
  2387.  * uses rubber sheet. The alternative would be porthole.
  2388.  *
  2389.  * It changes the Workstation Window (NPC) to the aspect ratio of the window.
  2390.  * It changes the Workstation Viewport (DC) to the size of the window.
  2391.  *
  2392.  * To do porthole, the Workstation Window would move around NPC. The
  2393.  * Workstation Viewport would still be the whole window.
  2394.  *
  2395.  * Watch out for X Window, View Window and Workstation Window confusion.
  2396.  */
  2397. void ResizeWorkstation(long wkid, int width, int height)
  2398. {
  2399.    float d, minx, maxx, miny, maxy;
  2400.    Plimit viewport;
  2401.    Plimit3 window;
  2402.  
  2403.    if (width > height) {
  2404.       minx = 0.0; maxx = 1.0;
  2405.       d = (float)(width-height)/(float)(2.0 * width);
  2406.       miny = d; maxy = 1.0 - d;
  2407.    }
  2408.    else {
  2409.       miny = 0.0; maxy = 1.0;
  2410.       d = (float)(height-width)/(float)(2.0 * height);
  2411.       minx = d; maxx = 1.0 - d;
  2412.    }
  2413.  
  2414.    viewport.x_min = 0.0;
  2415.    viewport.x_max = (float)width;
  2416.    viewport.y_min = 0.0;
  2417.    viewport.y_max = (float)height;
  2418.     
  2419.    pset_ws_vp( wkid, &viewport );
  2420.  
  2421.    window.x_min = (Pfloat)minx;
  2422.    window.x_max = (Pfloat)maxx;
  2423.    window.y_min = (Pfloat)miny;
  2424.    window.y_max = (Pfloat)maxy;
  2425.    window.z_min = 0.0;
  2426.    window.z_max = 1.0;
  2427.  
  2428.    pset_ws_win3( wkid, &window );
  2429. }
  2430.  
  2431.  
  2432. /*************************************************************************
  2433.  * InitLights - random init of two lights.
  2434.  */
  2435. InitLights(long wkid)
  2436. {
  2437.   Plight_src_bundle Light;
  2438.  
  2439.   /* Set the ambient light */
  2440.   Light.type = PLIGHT_AMBIENT;
  2441.   Light.rec.ambient.colr.type = PMODEL_RGB;
  2442.   Light.rec.ambient.colr.val.general.x = 0.7;    /* reddish gray */
  2443.   Light.rec.ambient.colr.val.general.y = 0.3;
  2444.   Light.rec.ambient.colr.val.general.z = 0.3;
  2445.   pset_light_src_rep(wkid, 1, &Light);
  2446.  
  2447.   /* Set the directional light */
  2448.   Light.type = PLIGHT_DIRECTIONAL;
  2449.   Light.rec.directional.colr.type = PMODEL_RGB;
  2450.   Light.rec.directional.colr.val.general.x = 1.0;    /* blue */
  2451.   Light.rec.directional.colr.val.general.y = 1.0;
  2452.   Light.rec.directional.colr.val.general.z = 1.0;
  2453.   /*
  2454.    * Note: the light source direction vector points from the light to the
  2455.    * object -  light should be in front, to the left, above 
  2456.    */
  2457.   Light.rec.directional.dir.delta_x =  1.0;
  2458.   Light.rec.directional.dir.delta_y = -1.0;
  2459.   Light.rec.directional.dir.delta_z = -1.0;
  2460.   NormalizeVector(&Light.rec.directional.dir);
  2461.   pset_light_src_rep(wkid, 2, &Light);
  2462. }
  2463.  
  2464. /*************************************************************************
  2465.  * NormalizeVector
  2466.  */
  2467. int 
  2468. NormalizeVector(v)
  2469. Pvec3 *v;
  2470. {
  2471.   register float len;
  2472.  
  2473. #define SQR(x) ((x)*(x))
  2474.  
  2475.   len = sqrt(SQR(v->delta_x) + SQR(v->delta_y) + SQR(v->delta_z));
  2476.   if (len == 0.0)
  2477.     return (0);
  2478.   len = 1.0 / len; /* divides are expensive, do this to save 2 divides */
  2479.   v->delta_x *= len;
  2480.   v->delta_y *= len;
  2481.   v->delta_z *= len;
  2482.   return (1);
  2483. }
  2484.  
  2485. /*************************************************************************
  2486.  * RotateObject - rather boring preemtive spinning of object. But it gets
  2487.  * it reset back to identity.
  2488.  *
  2489.  */
  2490. static void RotateObject(long wkid, long struxid, long count)
  2491. {
  2492.   Ppoint3 pt;
  2493.   Pvec3 shift;
  2494.   Pvec3 scale;
  2495.   Pfloat  x_ang;
  2496.   Pfloat  y_ang;
  2497.   Pfloat  z_ang;
  2498.   Pint    degree,
  2499.           err;
  2500.   Pmatrix3 bldmat;
  2501.   long step;
  2502.  
  2503.  
  2504.   step = 360/count;
  2505.  
  2506.   popen_struct(struxid);
  2507.  
  2508.   pset_edit_mode(PEDIT_REPLACE);
  2509.   pset_elem_ptr(MATRIX_ELEM);
  2510.  
  2511.   pt.x = 0.0;
  2512.   pt.y = 0.0;
  2513.   pt.z = 0.0;
  2514.   shift.delta_x = 0;
  2515.   shift.delta_y = 0;
  2516.   shift.delta_z = 0;
  2517.   scale.delta_x = 1.0;
  2518.   scale.delta_y = 1.0;
  2519.   scale.delta_z = 1.0;
  2520.  
  2521.  
  2522.   for (degree = 0; degree < 361; degree += step) {
  2523.     x_ang = RADIAN(degree);
  2524.     y_ang = 0;
  2525.     z_ang = 0;
  2526.     pbuild_tran_matrix3(&pt, &shift, x_ang, y_ang, z_ang, &scale, &err, bldmat);
  2527.     pset_local_tran3(bldmat, PTYPE_REPLACE);
  2528.     predraw_all_structs(wkid, PFLAG_ALWAYS);
  2529.   }
  2530.   for (degree = 0; degree < 361; degree += step) {
  2531.     x_ang = 0;
  2532.     y_ang = RADIAN(degree);
  2533.     z_ang = 0;
  2534.     pbuild_tran_matrix3(&pt, &shift, x_ang, y_ang, z_ang, &scale, &err, bldmat);
  2535.     pset_local_tran3(bldmat, PTYPE_REPLACE);
  2536.     predraw_all_structs(wkid, PFLAG_ALWAYS);
  2537.   }
  2538.   for (degree = 0; degree < 361; degree += step) {
  2539.     x_ang = 0;
  2540.     y_ang = 0;
  2541.     z_ang = RADIAN(degree);
  2542.     pbuild_tran_matrix3(&pt, &shift, x_ang, y_ang, z_ang, &scale, &err, bldmat);
  2543.     pset_local_tran3(bldmat, PTYPE_REPLACE);
  2544.     predraw_all_structs(wkid, PFLAG_ALWAYS);
  2545.  
  2546.   }
  2547.   /* reset it so we do not have to worry about translate on insert */
  2548.   protate_x(0.0, &err, bldmat);
  2549.   pset_local_tran3(bldmat, PTYPE_REPLACE); /* MATRIX_ELEM 7 */
  2550.  
  2551.   pclose_struct();
  2552.   pset_edit_mode(PEDIT_INSERT);
  2553. }
  2554.  
  2555. /*************************************************************************
  2556.  * StartSpinning - install oneSpin as a Motif "work proc"
  2557.  *
  2558.  * set up the Global theSpinInfo to allow oneSpin to incrementally spin
  2559.  * theNewStrux. This is installed as a Motif work proc and gets called
  2560.  * whenever the XtMainLoop has nothing better to do.
  2561.  *
  2562.  * SEE ALSO, StopSpinning().  This sets theSpinInfo.stop which gets returned
  2563.  * by oneSpin each time it is called.  A non-zero value mean that the work
  2564.  * proc is done.
  2565.  */
  2566. static void StartSpinning(long wkid, long struxid, long count)
  2567. {
  2568.  
  2569.   theSpinInfo.point.x = 0.0;
  2570.   theSpinInfo.point.y = 0.0;
  2571.   theSpinInfo.point.z = 0.0;
  2572.   theSpinInfo.offset.delta_x = 0;
  2573.   theSpinInfo.offset.delta_y = 0;
  2574.   theSpinInfo.offset.delta_z = 0;
  2575.   theSpinInfo.scale.delta_x = 1.0;
  2576.   theSpinInfo.scale.delta_y = 1.0;
  2577.   theSpinInfo.scale.delta_z = 1.0;
  2578.   theSpinInfo.x_ang = 0.0;
  2579.   theSpinInfo.y_ang = 0.0;
  2580.   theSpinInfo.z_ang = 0.0;
  2581.   theSpinInfo.delta_x = (float)6/count;
  2582.   theSpinInfo.delta_y = (float)4/count;
  2583.   theSpinInfo.delta_z = 0.0;
  2584.   theSpinInfo.strux_id = struxid;
  2585.   theSpinInfo.wk_id = wkid;
  2586.   theSpinInfo.dpy = XtDisplay(theDrawingArea);
  2587.   theSpinInfo.stop = 0;
  2588.  
  2589.   XtAppAddWorkProc(theAppContext,oneSpin,(XtPointer)&theSpinInfo);
  2590.  
  2591. }
  2592.  
  2593. /*************************************************************************
  2594.  * oneSpin - Motif "work proc" for spinning a structure
  2595.  */
  2596. Boolean oneSpin(char *client_data)
  2597. {
  2598.   SpinInfo *si;
  2599.   Pint error;
  2600.   Pmatrix3 matrix;
  2601.  
  2602.   si = (SpinInfo *)client_data;
  2603.  
  2604.   popen_struct(si->strux_id);
  2605.   pset_edit_mode(PEDIT_REPLACE);
  2606.   pset_elem_ptr(MATRIX_ELEM);
  2607.  
  2608.   si->x_ang += si->delta_x;
  2609.   si->y_ang += si->delta_y;
  2610.   si->z_ang += si->delta_z;
  2611.   pbuild_tran_matrix3(&si->point, &si->offset, 
  2612.               si->x_ang, si->y_ang, si->z_ang,
  2613.               &si->scale, &error, matrix);
  2614.   pset_local_tran3(matrix, PTYPE_REPLACE);
  2615.   predraw_all_structs(si->wk_id, PFLAG_ALWAYS);
  2616.   pclose_struct();
  2617.   pset_edit_mode(PEDIT_INSERT);
  2618.   XSync(si->dpy, 0);
  2619.  
  2620.   return (si->stop);
  2621. }
  2622.  
  2623. static void StopSpinning(long wkid)
  2624. {
  2625.   theSpinInfo.stop = 1;
  2626. }
  2627.  
  2628. /*************************************************************************
  2629.  * CreateDynGC - create an X GC Resource for Dynamics.
  2630.  *
  2631.  * Got the rubberbanding methodology from contrib/clients/xfig/w_drawPrim.c
  2632.  * But just the idea, no code was copied, hence no copyright.
  2633.  *
  2634.  * The idea is to xor ( exclusive or ) the foreground and the background
  2635.  * together. When it is xor'd with the background it produces the foreground.
  2636.  */
  2637. static GC CreateDynGC(Widget drawArea)
  2638. {
  2639.   XGCValues values;
  2640.   unsigned long fg, bg;
  2641.   GC tGC;
  2642.  
  2643.   XtVaGetValues(drawArea, XmNforeground, &fg, XmNbackground, &bg, NULL);
  2644.  
  2645.   values.foreground = fg ^ bg;
  2646.   values.background = bg;
  2647.   values.function = GXxor;
  2648.   tGC = XCreateGC(XtDisplay(drawArea),XtWindow(drawArea), 
  2649.           GCFunction | GCForeground | GCBackground, &values );
  2650.   return (tGC);
  2651. }
  2652. /*************************************************************************
  2653.  * ReadArchiveFile
  2654.  *
  2655.  * Find all of the root structures - first find all structres and weed out
  2656.  *  those that are instanced by others.
  2657.  * Read the whole archive, should do this be reading networks of posters, but..
  2658.  * Post all of the poster candidates.
  2659.  */
  2660. static int ReadArchiveFile(char *filename)
  2661. {
  2662.   Pint arid;
  2663.   Pint_list ids;  
  2664.   Pint junk[10];
  2665.   Pint posters[10], pCount;
  2666.   Pint nIDs;
  2667.   int i, j;
  2668.   Pint status;
  2669.   Pelem_ref_list_list *paths;
  2670.  
  2671. /*
  2672.  * Set the conflict resolution to always overwrite everything. Open Archive.
  2673.  */
  2674.   pset_conf_res(PRES_UPD, PRES_UPD);
  2675.   thePHIGSError = 0;
  2676.   popen_ar_file(arid, filename);
  2677.   if (thePHIGSError) {
  2678.     printf("Cannot open PHIGS Archive file %s\n", filename);
  2679.     return (thePHIGSError);
  2680.   }
  2681.  
  2682.   ids.ints = (Pint *)junk;
  2683.   pret_struct_ids(arid, 9, 0, &ids, &nIDs);
  2684.  
  2685.   printf("read archive %s, ret_struct_ids total %d, count = %d, first = %d\n",
  2686.      filename, nIDs, ids.num_ints, ids.ints[0] );
  2687.  
  2688.   if (thePHIGSStore == (Pstore)0) {
  2689.     pcreate_store(&i, &thePHIGSStore);
  2690.     if ( i != 0 ) printf("trouble crating store %d\n", i);
  2691.   }
  2692.  
  2693.   pCount = 0;
  2694.   for (i = 0; i < nIDs; i++ ) {
  2695. /*    printf("ret_ances i = %d, id = %d\n", i, ids.ints[i]); */
  2696.     pret_paths_ances(arid, ids.ints[i], PORDER_TOP_FIRST,
  2697.              1, thePHIGSStore, &paths, &status);
  2698.     if (status != 0) {
  2699.       printf("imagine a motif alarm! return archive ancestors error %d\n",
  2700.          status);
  2701.       continue;
  2702.     }
  2703.     if (paths->num_elem_ref_lists != 0) continue; /* instanced in archive */
  2704.     posters[pCount] = ids.ints[i]; pCount++;
  2705.   }
  2706.  
  2707.   pret_all_structs(arid);
  2708.   pclose_ar_file(arid);
  2709.  
  2710.   for (i = 0; i < pCount; i++ ) {
  2711.     ppost_struct(thePHIGSWorkstation, posters[i], 1.0);
  2712.   }
  2713. }
  2714.  
  2715. /*************************************************************************
  2716.  *  WriteArchiveFile
  2717.  */
  2718. static int WriteArchiveFile(char *filename)
  2719. {
  2720.   Pint arid;
  2721.   
  2722.   pset_conf_res(PRES_UPD, PRES_UPD);
  2723.   popen_ar_file(arid, filename);
  2724.   par_all_structs(arid);
  2725.   pclose_ar_file(arid);
  2726.  
  2727.   printf("closed archive file %s\n", filename);
  2728. }
  2729.  
  2730. /*************************************************************************
  2731.  *  DeleteAllStrux
  2732.  *
  2733.  * Currently, (a bug, I think), redraw_all_structs will not clear.
  2734.  */
  2735. static void DeleteAllStrux()
  2736. {
  2737.   pdel_all_structs();
  2738.   theNewStrux = 0;
  2739.  
  2740.   predraw_all_structs(thePHIGSWorkstation, PFLAG_ALWAYS);
  2741. }
  2742.  
  2743. /*************************************************************************
  2744.  * MyPHIGSErrorHandler - called by PHIGS when there is an error.
  2745.  *
  2746.  * This routine gets called instead of perr_hand() by the PHIGS library
  2747.  * when an error occurs.  It does exactly what perr_hand does except that
  2748.  * it also sets the global, thePHIGSError.  For sections of code that
  2749.  * need to know if an error has occurred, set thePHIGSError to zero and
  2750.  * make the calls, then check the global. See ReadArchiveFile().
  2751.  */
  2752. static void MyPHIGSErrorHandler( Pint errnum, Pint funcnum, char *fname)
  2753. {
  2754.   thePHIGSError = errnum;
  2755.   perr_log( errnum, funcnum, fname);
  2756. }
  2757.  
  2758. /*************************************************************************
  2759.  *
  2760.  */
  2761. static void fbInitView( XButtonPressedEvent *event ) 
  2762. {
  2763.   Pvec3 vpn;
  2764.   float tsinTheta;
  2765.     
  2766.   theDynX = event->x;
  2767.   theDynY = event->y;
  2768.  
  2769.   /* view plane normal */
  2770.   getNumberWidgetValue(k_view_pl_norm_x, &vpn.delta_x);
  2771.   getNumberWidgetValue(k_view_pl_norm_y, &vpn.delta_y);
  2772.   getNumberWidgetValue(k_view_pl_norm_z, &vpn.delta_z);
  2773.  
  2774.   NormalizeVector(&vpn); /* just in case the user was playing */
  2775.  
  2776.   /*
  2777.    * theta = atan2(cos(phi)*sin(theta), cos(phi)*cos(theta))
  2778.    */
  2779.   theTheta = atan2(vpn.delta_x, vpn.delta_z);
  2780.   /*
  2781.    * atan2(sin(theta), cos(theta)) gives theta.
  2782.    * since we have sin(phi) = dy and dx = cos(phi)*sin(theta)
  2783.    * we want atan2(dy, dx/sin(theta)) BUT sin(theta) will be zero
  2784.    * so we use dy*sin(theta) BUT when sin(theta) and dx are negative
  2785.    * it changes the quadrant. so...
  2786.    */
  2787.   tsinTheta = sin(theTheta);
  2788.   if (tsinTheta >= 0 ) {
  2789.    thePhi = atan2( vpn.delta_y * tsinTheta, vpn.delta_x);
  2790.   } else {
  2791.    thePhi = atan2( -(vpn.delta_y * tsinTheta), -vpn.delta_x);
  2792.   }
  2793.   
  2794.   thedebug = 1;
  2795.   printf("start t %g, p %g, x,y,z %g, %g, %g\n", theTheta, thePhi,  
  2796.    vpn.delta_x, vpn.delta_y, vpn.delta_z);
  2797. }
  2798. static void fbDynView( XMotionEvent *event )
  2799. {
  2800.   Pvec3 vpn;
  2801.   Pvec3 vup;
  2802.   float cx, cy, cz;
  2803.   int t, c;
  2804.         
  2805.   theTheta += 0.005 * (theDynX - event->x);
  2806.   thePhi   += 0.005 * (event->y - theDynY);
  2807.  
  2808.   theDynX = event->x;
  2809.   theDynY = event->y;
  2810.  
  2811.  
  2812.   vpn.delta_x = cos( thePhi ) * sin( theTheta );
  2813.   vpn.delta_y = sin( thePhi );
  2814.   vpn.delta_z = cos( thePhi ) * cos( theTheta );
  2815.  
  2816.   /* view up vector */
  2817.   getNumberWidgetValue(k_view_up_vect_x, &vup.delta_x);
  2818.   getNumberWidgetValue(k_view_up_vect_y, &vup.delta_y);
  2819.   getNumberWidgetValue(k_view_up_vect_z, &vup.delta_z);
  2820.  
  2821.   t = 6; c = 0;
  2822.   while (t--) {
  2823.     cx = vpn.delta_y*vup.delta_z - vpn.delta_z*vup.delta_y;
  2824.     cy = vpn.delta_z*vup.delta_x - vpn.delta_x*vup.delta_z;
  2825.     cz = vpn.delta_x*vup.delta_y - vpn.delta_y*vup.delta_x;
  2826.   
  2827.     if ((cx*cx + cy*cy + cz*cz) < 0.1) {
  2828.         if ((vup.delta_y < 0.8) && (vup.delta_y > -0.8)) {
  2829.           vup.delta_y += 0.03;
  2830.         } else {
  2831.           vup.delta_x += 0.05;
  2832.         }
  2833.         NormalizeVector(&vup);
  2834.         c = 1;
  2835.     } else {
  2836.         t = 0;
  2837.     }
  2838.   }
  2839.  
  2840.   if (c) {
  2841.     setNumberWidgetValue(k_view_up_vect_x, vup.delta_x);
  2842.     setNumberWidgetValue(k_view_up_vect_y, vup.delta_y);
  2843.     setNumberWidgetValue(k_view_up_vect_z, vup.delta_z);
  2844.   }      
  2845.   setNumberWidgetValue(k_view_pl_norm_x, vpn.delta_x);
  2846.   setNumberWidgetValue(k_view_pl_norm_y, vpn.delta_y);
  2847.   setNumberWidgetValue(k_view_pl_norm_z, vpn.delta_z);
  2848.  
  2849.   applyViewSet(1);
  2850.    
  2851. }
  2852. static void fbEndView( XButtonReleasedEvent *event )
  2853. {
  2854.   Window root, child;
  2855.   int root_x, root_y;
  2856.   int win_x, win_y;
  2857.   unsigned int keys_buttons;
  2858.       
  2859.   XQueryPointer(XtDisplay(theDrawingArea),XtWindow(theDrawingArea),
  2860.                 &root, &child, &root_x, &root_y, &win_x, &win_y,
  2861.                 &keys_buttons);
  2862.   XQueryPointer(XtDisplay(theDrawingArea),XtWindow(theDrawingArea),
  2863.                 &root, &child, &root_x, &root_y, &win_x, &win_y,
  2864.                 &keys_buttons);
  2865.                 
  2866.     if ((win_x != theDynX) && (win_y != theDynY)) {
  2867.         printf("spinning... %d, %d, %d, %d\n", 
  2868.         theDynX,win_x,theDynY,win_y);
  2869.     }
  2870. }
  2871.  
  2872. /*************************************************************************
  2873.  * ApplySurfaceAttrs
  2874.  */
  2875. void
  2876. ApplySurfaceAttrs()
  2877. {
  2878.   Pint error, ptr;
  2879.   Pint errind;
  2880.   Pelem_data *data;
  2881.   Pelem_type eType;
  2882.   size_t eSize;
  2883.   Pint_style style;
  2884.   Pint shade;
  2885.   Pint cull;
  2886.   float value;
  2887. #ifndef NO_TRANS
  2888.   Pxrefl_props reflProps;
  2889. #else
  2890.   Prefl_props reflProps;
  2891. #endif
  2892.  
  2893.   MrmCode class;
  2894.  
  2895.   if (theSurfaceForm == NULL) {     /* The first time, fetch order box. */
  2896.     if (MrmFetchWidget(theMrmHierarchy, "surface_dialog", theTopLevel,
  2897.                &theSurfaceForm, &class) != MrmSUCCESS) {
  2898.       printf("can't fetch Surface set dialog");
  2899.       return;
  2900.     }
  2901.   }
  2902.  
  2903.   if (theSelectedElement == -1) return;
  2904.  
  2905.   popen_struct(theSelectedStrux);
  2906.  
  2907.   if (XmToggleButtonGetState(widgetArray[k_sstyle_hollow]))
  2908.     style = PSTYLE_HOLLOW;
  2909.   else if (XmToggleButtonGetState(widgetArray[k_sstyle_solid]))
  2910.     style = PSTYLE_SOLID;
  2911.   else if (XmToggleButtonGetState(widgetArray[k_sstyle_empty]))
  2912.     style = PSTYLE_EMPTY;
  2913.   else {
  2914.     printf("bad style\n");
  2915.     style = PSTYLE_SOLID;
  2916.   }
  2917.  
  2918.   pset_elem_ptr(INT_STYLE_ELEM);
  2919.   pdel_elem();
  2920.   pset_int_style(style);
  2921.  
  2922.   if (XmToggleButtonGetState(widgetArray[k_sshade_flat]))
  2923.     shade = PSD_NONE;
  2924.   else if (XmToggleButtonGetState(widgetArray[k_sshade_gouraud]))
  2925.     shade = PSD_COLOUR;
  2926.   else if (XmToggleButtonGetState(widgetArray[k_sshade_dot]))
  2927.     shade = PSD_DOT_PRODUCT;
  2928.   else if (XmToggleButtonGetState(widgetArray[k_sshade_phong]))
  2929.     shade = PSD_NORMAL;
  2930.   else {
  2931.     printf("bad shade\n");
  2932.     shade = PSD_COLOUR;
  2933.   }
  2934.   pset_elem_ptr(INT_SHAD_ELEM);
  2935.   pdel_elem();
  2936.   pset_int_shad_meth(shade);
  2937.  
  2938.   if (XmToggleButtonGetState(widgetArray[k_cull_none]))
  2939.     cull = PCULL_NONE;
  2940.   else if (XmToggleButtonGetState(widgetArray[k_cull_back]))
  2941.     cull = PCULL_BACKFACE;
  2942.   else if (XmToggleButtonGetState(widgetArray[k_cull_front]))
  2943.     cull = PCULL_FRONTFACE;
  2944.   else {
  2945.     printf("bad cull\n");
  2946.     cull = PCULL_NONE;
  2947.   }
  2948.  
  2949.   if (thePHIGSStore == (Pstore)0) {
  2950.     pcreate_store(&errind, &thePHIGSStore);
  2951.     if ( errind != 0 ) printf("trouble crating store %d\n", errind);
  2952.     goto end;
  2953.   }
  2954.   
  2955.   pset_elem_ptr(FACE_CULL_MODE);
  2956.   pinq_cur_elem_type_size(&errind,&eType,&eSize);
  2957.   if (errind != 0) goto end;
  2958.   
  2959.   if (eType == PELEM_FACE_CULL_MODE) pdel_elem(); else {
  2960.     poffset_elem_ptr(-1);
  2961.     theSelectedElement++;
  2962.   }
  2963.   pset_face_cull_mode(cull);
  2964.  
  2965. #ifndef NO_TRANS
  2966.   if (getWidgetValue(k_surface_refl_transparency, &value)) goto end;
  2967.   if (value > /* arbitrary threshold for transparency */0.00001 ) {
  2968.     reflProps.transpar_coef = value;
  2969.   } else     reflProps.transpar_coef = 0.0;
  2970. #endif
  2971.     
  2972.   if (getWidgetValue(k_surface_refl_ambient, &value)) goto end;
  2973.   reflProps.ambient_coef = value;    /* ambient coefficient */
  2974.   if (getWidgetValue(k_surface_refl_diffuse, &value)) goto end;
  2975.   reflProps.diffuse_coef = value;    /* diffuse coefficient */
  2976.   if (getWidgetValue(k_surface_refl_specular, &value)) goto end;
  2977.   reflProps.specular_coef = value;    /* specular coefficient */
  2978.   /* set specular color to white */
  2979.   reflProps.specular_colr.type = PMODEL_RGB;    /* specular color model */
  2980.   reflProps.specular_colr.val.general.x = 1.0;
  2981.   reflProps.specular_colr.val.general.y = 1.0;
  2982.   reflProps.specular_colr.val.general.z = 1.0;
  2983.   if (getWidgetValue(k_surface_refl_specexp, &value)) goto end;
  2984.   reflProps.specular_exp = value;    /* specular exponent */
  2985.  
  2986.   pset_elem_ptr(REFL_PROPS_ELEM);
  2987.   pdel_elem();
  2988.  
  2989. #ifndef NO_TRANS
  2990.   pxset_refl_props(&reflProps);
  2991. #else
  2992.   pset_refl_props(&reflProps);
  2993. #endif
  2994.  
  2995.  end:
  2996.   pclose_struct();
  2997.  
  2998. }
  2999.  
  3000. /*************************************************************************
  3001.  * The following routine is taken from Tom Gaskin's example light_toy.c
  3002.  * (would that the light form were there, too!)
  3003.  * build_sphere only.
  3004.  * It is copyright Tom Gaskins, O'Reilly & Associates, Inc. 1992.
  3005.  * See the book, page xxxvi for further details.
  3006.  */
  3007.  
  3008. #define NUM_LONG_FACETS        32
  3009. #define NUM_LONG_POINTS        (NUM_LONG_FACETS + 1)
  3010. #define NUM_LAT_FACETS        16
  3011. #define NUM_LAT_POINTS        (NUM_LAT_FACETS + 1)
  3012. #define RADIUS 1.3
  3013.  
  3014. static void
  3015. build_sphere(long struxID)
  3016. {
  3017.   Pptnorm3        vertex_data[NUM_LONG_POINTS * NUM_LAT_POINTS];
  3018.   Pfacet_vdata_arr3    vertices;
  3019.   Pint_size        array_dims;
  3020.   double        theta = 0, phi = 0;
  3021.   int            i, j, index;
  3022.   
  3023.   Ppoint_list3 plist;
  3024.   
  3025.   Ppoint3 p[2];
  3026.   
  3027.   for ( i = 0; i < NUM_LAT_POINTS; i++ ) {
  3028.     for ( j = 0; j < NUM_LONG_FACETS; j++ ) {
  3029.       index = i * NUM_LONG_POINTS + j;
  3030.       vertex_data[index].norm.delta_x = - sin(phi) * cos(theta);
  3031.       vertex_data[index].norm.delta_y = - cos(phi); 
  3032.       vertex_data[index].norm.delta_z = - sin(phi) * sin(theta);
  3033.       vertex_data[index].point.x = RADIUS * 1+ vertex_data[index].norm.delta_x;
  3034.       vertex_data[index].point.y = RADIUS * 1+ vertex_data[index].norm.delta_y;
  3035.       vertex_data[index].point.z = RADIUS * 1+ vertex_data[index].norm.delta_z;
  3036.       theta += (2 * M_PI) / NUM_LONG_FACETS;
  3037.     }
  3038.     phi += M_PI / NUM_LAT_FACETS;
  3039.     
  3040.     /* Close the circle. */
  3041.     index = i * NUM_LONG_POINTS + NUM_LONG_FACETS;
  3042.     vertex_data[index].point = vertex_data[index - NUM_LONG_FACETS].point;
  3043.     vertex_data[index].norm = vertex_data[index - NUM_LONG_FACETS].norm;
  3044.   }
  3045.   
  3046.   InitStrux(struxID);
  3047.   popen_struct(struxID);
  3048.   vertices.ptnorms = vertex_data;
  3049.   array_dims.size_x = NUM_LONG_POINTS;
  3050.   array_dims.size_y = NUM_LAT_POINTS;
  3051.   pset_int_colr_ind(2);
  3052.   pquad_mesh3_data( PFACET_NONE, PVERT_COORD_NORMAL, PMODEL_RGB,
  3053.            &array_dims, (Pfacet_data_arr3 *)NULL, &vertices );
  3054.   pset_line_colr_ind(4);
  3055.   
  3056.   p[0].x = 0; p[0].y = 0; p[0].z = 0;
  3057.   p[1].x = 1; p[1].y = 1; p[1].z = 1;
  3058.   plist.points = p;
  3059.   plist.num_points = 2;
  3060.   ppolyline3( &plist );
  3061.   
  3062.   pclose_struct();
  3063. }
  3064.